通用类不绑定到HierarchicalDataTemplate

时间:2012-12-10 16:04:43

标签: c# wpf treeview hierarchicaldatatemplate

我是WPF的新手,所以可能会遗漏一些显而易见的东西,但无法在任何地方找到答案。

基本上我构建了一个以特定方式排序的自定义树集合,并且树的节点被输入到集合的类型中。在TreeView中进行测试时,HierarchicalDataTemplate在节点是通用的时候不起作用。如果他们不通用,那就没问题了。

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

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;
        }
    }
}

然后在xaml中:

HierarchicalDataTemplate DataType="{x:Type local:SimpleNode`1}" ItemsSource="{Binding Children}"

显然,附加到该类型的`1是SimpleNode具有1个通用参数的结果。如果我删除了泛型类HierarchicalDataTemplate,我可以查看TreeView中的树。随着仿制药的到位,它不会做到这一点。

有什么想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

没有开箱即用的支持。但是你可以通过创建自己的支持泛型的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 我提供的实现通过简单地检查项目的类型添加了对开放泛型类型的支持。如果它是通用的,我们将自己变为开放的泛型类型(通过GetGenericTypeDefinition)并将其用作密钥。

要实际使用此选择器,我们必须告诉TreeView它应该使用它。我们通过指定ItemTemplateSelector

来做到这一点