1

我是 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. 有了泛型,它就不会这样做。

有任何想法吗?

提前致谢。

4

1 回答 1

4

没有开箱即用的支持。但是您可以通过创建自己的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.

于 2012-12-10T16:13:30.910 回答