C# 泛型类不';t绑定到HierarchycalDataTemplate

C# 泛型类不';t绑定到HierarchycalDataTemplate,c#,wpf,treeview,hierarchicaldatatemplate,C#,Wpf,Treeview,Hierarchicaldatatemplate,我是WPF的新手,所以可能遗漏了一些明显的东西,但一直没有找到答案 基本上,我正在构建一个定制的树集合,它以特定的方式进行排序,树的节点被类型化为集合的类型。在TreeView中进行测试时,如果节点是泛型的,hierarchycaldatatemplate不起作用。如果它们不是通用的,也没关系 下面是一个简单的节点类来说明: public class SimpleNode<T> { private List<SimpleNode<T>> _childr

我是WPF的新手,所以可能遗漏了一些明显的东西,但一直没有找到答案

基本上,我正在构建一个定制的树集合,它以特定的方式进行排序,树的节点被类型化为集合的类型。在
TreeView
中进行测试时,如果节点是泛型的,
hierarchycaldatatemplate
不起作用。如果它们不是通用的,也没关系

下面是一个简单的节点类来说明:

public class SimpleNode<T>
{
    private List<SimpleNode<T>> _children;
    private string _name;

    public SimpleNode(string name)
    {
        _name = name;
    }

    public List<SimpleNode<T>> Children
    {
        get
        {
            return _children;
        }
        set
        {
            _children = value;
        }
    }

    public string Name
    {
        get
        {
            return _name;
        }
    }
}
显然,附加到类型的'1'是
SimpleNode
具有1个泛型参数的结果。如果我去掉泛型类,
hierarchycaldatatemplate
可以工作,我可以在
TreeView
中查看树。有了泛型,它就做不到了

有什么想法吗


提前感谢。

没有现成的支持。但您可以通过创建自己的支持泛型的
DataTemplateSelector
来实现这一点:

public class OpenGenericTypeDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item,
                                                DependencyObject container)
    {
        var element = container as FrameworkElement;
        if (item != null && element != null)
        {
            if (item.GetType().IsGenericType)
            {
                var genericTypeDefinition = item.GetType()
                                                .GetGenericTypeDefinition();
                var key = new DataTemplateKey(genericTypeDefinition);
                return element.TryFindResource(key) as DataTemplate;
            }
        }

        return null;
    }
}
您可以这样使用它:

<UserControl.Resources>
  <OpenGenericTypeDataTemplateSelector x:Key="GenericTemplateSelector" />
</UserControl.Resources>
...
<TreeView ItemTemplateSelector="{StaticResource GenericTemplateSelector}" ...>
  <TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:SimpleNode`1}"
                              ItemsSource="{Binding Children}">
      ...
    </HierarchicalDataTemplate>
  </TreeView.Resources>

...
...
这实际上非常简单:
当您为某个类型创建
DataTemplate
时,该类型的名称将自动成为该模板的键。
默认的
DataTemplateSelector
使用项的类型作为查找值。但是泛型类实例的类型是封闭泛型类型,即指定了泛型类型参数的类型。
问题是:模板已注册为开放泛型类型,即未指定泛型类型参数。这就是为什么默认的
DataTemplateSelector
不会选择注册为打开泛型类型的
DataTemplate
s。
我提供的实现通过简单地检查项目的类型来增加对开放泛型类型的支持。如果它是泛型的,我们就得到开放的泛型类型(通过
GetGenericTypeDefinition
)并将其用作键


要真正使用这个选择器,我们必须告诉
TreeView
它应该使用它。我们通过指定
ItemTemplateSelector

来实现这一点,没有现成的支持。但您可以通过创建自己的支持泛型的
DataTemplateSelector
来实现这一点:

public class OpenGenericTypeDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item,
                                                DependencyObject container)
    {
        var element = container as FrameworkElement;
        if (item != null && element != null)
        {
            if (item.GetType().IsGenericType)
            {
                var genericTypeDefinition = item.GetType()
                                                .GetGenericTypeDefinition();
                var key = new DataTemplateKey(genericTypeDefinition);
                return element.TryFindResource(key) as DataTemplate;
            }
        }

        return null;
    }
}
您可以这样使用它:

<UserControl.Resources>
  <OpenGenericTypeDataTemplateSelector x:Key="GenericTemplateSelector" />
</UserControl.Resources>
...
<TreeView ItemTemplateSelector="{StaticResource GenericTemplateSelector}" ...>
  <TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:SimpleNode`1}"
                              ItemsSource="{Binding Children}">
      ...
    </HierarchicalDataTemplate>
  </TreeView.Resources>

...
...
这实际上非常简单:
当您为某个类型创建
DataTemplate
时,该类型的名称将自动成为该模板的键。
默认的
DataTemplateSelector
使用项的类型作为查找值。但是泛型类实例的类型是封闭泛型类型,即指定了泛型类型参数的类型。
问题是:模板已注册为开放泛型类型,即未指定泛型类型参数。这就是为什么默认的
DataTemplateSelector
不会选择注册为打开泛型类型的
DataTemplate
s。
我提供的实现通过简单地检查项目的类型来增加对开放泛型类型的支持。如果它是泛型的,我们就得到开放的泛型类型(通过
GetGenericTypeDefinition
)并将其用作键


要真正使用这个选择器,我们必须告诉
TreeView
它应该使用它。我们通过指定
ItemTemplateSelector

来实现这一点。非常感谢,我将仔细查看,看看是否可以了解您在这里做了什么。另外,为了快速解决问题,我找到了另一篇文章,建议创建一个非泛型基类并在WPF中引用它——这似乎也可行。[链接]@user1373164:我在这里添加了一个解释。当然,非泛型基类可以工作,但它只是标准
DataTemplateSelector
实现的一个短期解决方案,因此我不建议使用它。非常感谢,我将仔细查看,看看是否可以了解您在这里做了什么。另外,为了快速解决问题,我找到了另一篇文章,建议创建一个非泛型基类并在WPF中引用它——这似乎也可行。[链接]@user1373164:我在这里添加了一个解释。当然,非泛型基类可以工作,但它只是标准
DataTemplateSelector
实现的短期解决方案,因此我不建议使用它。