当从 DataTemplateSelector 显式返回 DataTemplate 时,为什么 DataTemplate 无法绑定到接口?

2024-04-13

我创建了一个 DataTemplateSelector,它是使用一组已知接口进行初始化的。如果传递到选择器的项目实现了这些接口之一,则返回关联的数据模板。

首先,这是有问题的 ICategory 接口......

public interface ICategory
{
    ICategory ParentCategory { get; set; }
    string    Name           { get; set; }

    ICategoryCollection Subcategories { get; }
}

这是 DataTemplateSelector,它基于基类或接口进行匹配,而不仅仅是特定的具体类......

[ContentProperty("BaseTypeMappings")]
public class SubclassedTypeTemplateSelector : DataTemplateSelector
{
    private delegate object TryFindResourceDelegate(object key);

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var frameworkElement = container as FrameworkElement;

        foreach(var baseTypeMapping in BaseTypeMappings)
        {
            // Check if the item is an instance of, a subclass of,
            // or implements the interface specified in BaseType
            if(baseTypeMapping.BaseType.IsInstanceOfType(item))
            {
                // Create a key based on the BaseType, (not item.DataType as usual)
                var resourceKey = new DataTemplateKey(baseTypeMapping.BaseType);

                // Get TryFindResource method from either the FrameworkElement,
                // or from the application
                var tryFindResource = (frameworkElement != null)
                    ? (TryFindResourceDelegate)frameworkElement.TryFindResource
                    : Application.Current.TryFindResource;

                // Use the TryFindResource delegate from above to try finding
                // the resource based on the resource key
                var dataTemplate = (DataTemplate)tryFindResource(resourceKey);
                dataTemplate.DataType = item.GetType();
                if(dataTemplate != null)
                    return dataTemplate;
            }
        }

        var defaultTemplate = DefaultDataTemplate ?? base.SelectTemplate(item, container);
        return defaultTemplate;
    }

    public DataTemplate DefaultDataTemplate { get; set; }

    public Collection<BaseTypeMapping> BaseTypeMappings { get; } = new Collection<BaseTypeMapping>();
}

public class BaseTypeMapping
{
    public Type BaseType { get; set; }
}

以下是它在资源中的设置方式以及相应的 HierarchicalDataTemplate(DataType = ICategory)...

    <HierarchicalDataTemplate DataType="{x:Type model:ICategory}"
        ItemsSource="{Binding Subcategories}">

        <TextBlock Text="{Binding Name}" />

    </HierarchicalDataTemplate>

    <is:SubclassedTypeTemplateSelector x:Key="SubclassedTypeTemplateSelector">
        <!--<is:BaseTypeMapping BaseType="{x:Type model:ICategory}" />-->
    </is:SubclassedTypeTemplateSelector>

最后,这是一个使用它的 TreeView...

<TreeView x:Name="MainTreeView"
    ItemsSource="{Binding Categories}"
    ItemTemplateSelector="{StaticResource SubclassedTypeTemplateSelector}" />

我已经调试过了并且可以确认返回的数据模板正确按预期到 TreeView 并逐步执行代码,因为TreeView 正在根据 ItemSource 绑定正确加载子类别在分层数据模板上。所有这一切都按预期进行。

不起作用的是模板本身的内容。正如您所看到的,模板只是应该显示类别的名称,但它只是呈现原始对象,就好像它直接放置在 ContentPresenter 中一样,没有任何模板。您在 UI 中看到的只是 ToString 的结果。模板的内容被完全忽略。

我唯一能想到的是它不起作用,因为我正在使用 DataType 的接口,但同样,子项 ItemsSource 的绑定确实有效,所以我在这里有点困惑。

值得注意的是:作为测试,我根据具体类型(即类别而不仅仅是 ICategory)创建了第二个 DataTemplate,当我这样做时,它按预期工作。问题是具体类型位于 UI 不应该引用的程序集中。这就是我们首先使用接口的全部原因。

*注意:我还尝试通过使用 Key 而不是设置 DataType 属性来更改查找模板的方式。在这种情况下,就像以前一样,选择器仍然找到相同的资源,但仍然不起作用!

然而讽刺的是,如果我使用相同的键通过 StaticResource 绑定直接设置 TreeView 的 ItemTemplate,那么它does有效,这意味着只有当我从选择器返回模板时它才不起作用not出现与是否设置 DataType 有关。*


不起作用的是模板本身的内容

这是因为,由于 DataType 属性设置为接口类型,因此未应用您在 XAML 标记中定义的模板。正如 @Manfred Radlwimmer 所说,这是设计使然:https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e774a24-0deb-4acd-a719-32abd847041d/data-templates-and-interfaces?forum=wpf https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e774a24-0deb-4acd-a719-32abd847041d/data-templates-and-interfaces?forum=wpf。从 DataTemplateSelector 返回这样的模板并不会让它像您已经发现的那样工作。

但是,如果您使用 DataTemplateSelector 选择适当的数据模板,您可以从数据模板中删除 DataType 属性,并为每个模板指定一个唯一的 x:Key:

<HierarchicalDataTemplate x:Key="ICategory" ItemsSource="{Binding Subcategories}">
    <TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>

然后您应该能够使用此密钥解析资源,例如:

var baseTypeName = "ICategory";
var dataTemplate = (DataTemplate)tryFindResource("baseTypeName");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当从 DataTemplateSelector 显式返回 DataTemplate 时,为什么 DataTemplate 无法绑定到接口? 的相关文章

随机推荐

  • 经典 ASP XLS 输出,单元格中带有回车符

    我有一个经典的 ASP 脚本 它将 HTML 表输出为 XLS 文件 但没有运气让回车符 换行符在单个单元格中工作 为了进行测试 我使用基于克里斯托夫响应的代码如何从经典 ASP 输出 Excel xls 文件 https stackove
  • 如何将 Netezza 中的日期从时间戳格式转换为 yyyymmdd?

    如何将 Netezza 中的日期从时间戳格式转换为 yyyymmdd 使用以下查询转换为日期格式 select TO CHAR DATE 2009 12 23 23 45 58 YYYY MM DD or select TO CHAR TO
  • 如何获取子元素相对于父元素的位置?

    如果有 Canvas 父级 则很容易获得子级的位置 Canvas GetLeft Top child 但是对于其他类型的父母我怎样才能得到孩子的位置呢 可以使用以下方法完成TranslatePoint的控制方法 UIElement cont
  • Java、Lucene:在Java中设置IndexWriter的锁定超时。

    我正在致力于将 Lucene 与我们基于 Spring MVC 的应用程序集成 目前我们已经可以使用它了 但是我们很少得到cannot obtain lock错误 之后我必须手动删除锁定文件才能正常工作 如何在 Java 中设置锁定索引的超
  • 如何使用动态名称实现 property() (在 python 中)

    我正在对单个神经元进行模拟编程 因此我必须处理很多参数 现在的想法是我有两个类 一个用于 SingleParameter 一个用于参数集合 我使用 property 来轻松访问参数值并使代码更具可读性 这非常适合 sinlge 参数 但我不
  • iPhone、核心数据和 JSON

    我有一个带有 API 的网站 它使用 JSON 发布信息 我可以很好地访问这个 API 但我真的很想使用 Core Data 将信息存储在 iPhone 应用程序中 有没有办法将持久存储连接到 JSON API 这样我就可以使用网站作为核心
  • 在 istio 中为 envoy 启用 http 标头日志记录

    我希望能够捕获 日志 至少部分 envoy我的 HTTP 标头istio服务网格 我已经经历过envoy s docs https www envoyproxy io docs envoy latest start quick start
  • 具有“不同于”的子集函数?

    是否可以通过说 subset dataset IA LABEL not equal to Er or Sie or Es or wird or gleich 之类的东西来使用子集函数 我感兴趣的是 不等于 运算符 子集函数有类似的东西吗 谢
  • 从文本文件中读取字符串和整数

    假设我有一个如下所示的文件 51 41 52 07 52 01 51 22 50 44 49 97 Coal Diggers 77 26 78 33 78 29 78 12 77 09 75 74 Airplane Flyers 31 25
  • 用Java删除锁定的文件?

    我们必须使用 Windows 上运行的 Java 来删除一些目录及其内容 我担心会遇到被锁定的目录文件 我们可以调用Unlocker http www emptyloop com unlocker 进行删除 或者是否有更以 Java 为中心
  • 在 Swift 中通过 TouchID 生成哈希或字符串 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我想在 Swift 中通过 iPhone 上的 Touch ID 创建一个唯一的字符串或散列 我搜索了很多 但没有找到解决方案 你不可以做这
  • 如何删除 POI 生成的 Excel 中的警告?

    I am using Apache POI for writing content into excel sheet after generating an excel in all the cells which ever cell ha
  • 当被调用的 Activity 退出时,如何以自然的方式返回结果?

    什么工作正常 我的应用程序中有 2 个活动 第一个活动调用第二个活动来获取结果 第二个活动显示了新的布局并允许用户执行某些操作 有一个 确定 按钮 当用户按下此按钮时 第二个活动完成并且用户返回到第一个活动 在幕后 第一个活动像这样调用第二
  • 颤动中底片内的文本框

    我有一个如下所示的底页 It has a text box inside it when I cliked on that I am getting something like 我的文本框完全被键盘覆盖 有什么办法可以解决这个问题吗 下面
  • 获取 Android 上的活动驱动程序列表

    有没有一种简单的方法来获取 Android 设备上当前使用的驱动程序列表 lsmod列出了少量驱动程序 3 但我猜测大多数驱动程序都编译到内核中而不是作为模块 显然 像这样的事情make menuconfig由于设备本身缺乏开发工具 没有机
  • 模板参数数量错误的模板参数

    考虑一个模板类 C 它具有通过模板模板参数设置的策略和两个策略定义 template
  • Python应用程序引擎:如何保存图像?

    这是我从 flex 4 文件参考上传中得到的 自我请求 Request POST UPLOAD Accept text Cache Control no cache Connection Keep Alive Content Length
  • 如何找到一个向量中与另一个向量最接近的值?

    我有两个大小相等的向量 例如 A 2 29 2 56 2 77 2 90 2 05 and B 2 34 2 62 2 67 2 44 2 52 我有兴趣在两个相同大小的向量 A 和 B 中找到最接近的值 几乎相等 即在 A 中的所有元素中
  • Zend 框架 website.com/username

    我正在使用 Zend Framework 开发的应用程序之一要求通过 website com username 访问用户的个人资料页面 而其他页面应通过 website com controller name action name 访问
  • 当从 DataTemplateSelector 显式返回 DataTemplate 时,为什么 DataTemplate 无法绑定到接口?

    我创建了一个 DataTemplateSelector 它是使用一组已知接口进行初始化的 如果传递到选择器的项目实现了这些接口之一 则返回关联的数据模板 首先 这是有问题的 ICategory 接口 public interface ICa