0

我知道有很多在 wpf 中使用树视图的例子。我知道这很难相信,但我认为我有一个合理的问题尚未被 StackOverflow 上关于树视图的无数问题所解决。

TL;DR版本:尝试了很多东西。看了很多网站。有复杂的树结构。寻找一种简单的方法来实现所需的树结果。底部的问题。)

所以这里...

我读过Josh 在 TreeViews 上的著名帖子

当然,Philipp Sumi有关于使用 TreeViews 的非常有用的帖子。

所需输出的要点是不同类型的项目在其各自的标题下呈现,并且对象可以在不同的位置表示两次。建议单独使用 DataTemplateSelector 不会为我提供所需的TreeView.

期望的输出:

Root  
 |--Header A (People)
      |---Person A1 (Jane)
      |---Person A2 (Steve)
 |--Header B (Cars)
      |---Car B1 (Red Car)
      |---Car B2 (Blue Car)
            |---Person A1 (Jane)
            |---Person A3 (Jon)

注意:A3 是 Jon Skeet ,SO 的 Chuck Noris

我的方法的第一部分基本上是使用 aCompositeCollection虽然我实际上并没有使用它。尽管如此,这篇文章似乎表明它不会解决我的问题。作为人,即。史蒂夫,他的数据中没有其他人、汽车或任何其他对象,所以他是一个最终项目。

查看型号:

我绑定的是:

public ObservableCollection<object> Children
    {
        get
        {
            ObservableCollection<object> childNodes = new ObservableCollection<object>();
            foreach (var person in PeopleCollection)
                childNodes.Add(person);
            foreach (var car in CarCollection)
                childNodes.Add(car);
            return childNodes;
        }
    }

模板选择器:

我们必须在 TreeView 中管理多种类型的对象,所以我使用 DataTemplateSelector,如下所示:

class MyTemplateSelector : DataTemplateSelector
{
    public HierarchicalDataTemplate CarTemplate { get; set; }
    public HierarchicalDataTemplate PeopleTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item.GetType() == typeof(Car))
            return CarTemplate;
        if (item.GetType() == typeof(Person))
            return (PeopleTemplate);
        return (null);
    }
}

XAML:

最后,有一些 XAML 可以很好地将它们捆绑在一起。

    <UserControl.Resources>
    <HierarchicalDataTemplate x:Key="m_CarTemplate"
                              DataType="{x:Type local:Car}"
                              ItemsSource="{Binding People}" >
        <TextBlock Text="{Binding CarColor}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate x:Key="m_PeopleTemplate"
                              DataType="{x:Type local:Person}">
        <TextBlock Text="{Binding PersonName}" />
    </HierarchicalDataTemplate>

    <local:ProjectTemplateSelector
        CarTemplate="{StaticResource m_CarTemplate}"
        PeopleTemplate ="{StaticResource m_PeopleTemplate}"
        x:Key="myTemplateSelector"/>
      </UserControl.Resources>

在 XAML 中再往下一点:

    <TreeView Width="Auto" Height="Auto" HorizontalAlignment="Left"
                  VerticalAlignment="Top" Margin="0,0,0,0" Name="m_TreeView"
                  ItemsSource="{Binding ViewModel.Children}"
                  ItemTemplateSelector="{StaticResource myTemplateSelector}"
                  />

潜在的解决方案:

Philipp 方法的主要挫折是我真的只想在第一级设置类别,理想情况下是通过,<TreeViewItem Header="Cars" />但似乎它会失败。接下来,我没有这些类别级别项目的项目,即。汽车和人,只是字符串。我想我可以制作这些占位符对象,并给它们各自的集合,而不是在我的 viewModel 上用它们制作属性,但这似乎有点过分只是为了获得一些标题......特别是因为已经存在。

第二种选择是CompositeCollection 方法,有一个很好的例子,但我不完全确定它会解决我的问题。一方面,我没有看到它在 TreeView 中使用过,所以我不确定它是否会适当地应用在那里,我想使用 TreeView 来保留数据的层次结构。

最后,我尝试了自己的变体,在其中HierarchicalDataTemplate添加了 a<TreeViewItem Header="Cars" />但这不起作用,因为每辆 Car 都有自己的标题。

问题

主要问题:通过绑定来实现所需的 TreeView 结构的适当方法是什么?因此产生的结果是所有汽车都显示在 Cars 标题下,People 显示在 People 标题下,除了位于 Cars.PeopleCollection 中的人也显示为相应 Car 对象的子对象。

第二个问题:专门为 TreeViewItems 创建一个 Wrapper 类是一种常见且适当的方法吗?那是我应该做的吗?正如我在 Philipp 的潜在解决方案中所描述的那样。

我还应该提到,鉴于我在这里描述的解决方案,代码可以编译。问题是没有标题。下一个问题是在我将人员添加到汽车后,然后尝试扩展汽车,我收到以下错误:Must disconnect specified child from current parent Visual before attaching to new parent Visual.我认为这是这行代码的产物:ObservableCollection<object> childNodes = new ObservableCollection<object>();但坦率地说,它已经晚了,我很累,所以我可以不要想出合适的方法来做到这一点,也许 CompositeCollection 是我需要的。

4

1 回答 1

1

要添加类别标题,我看到了两种可能的解决方案。

第一个是创建一个对象“类别”并将其添加到您的子集合中。然后,您创建与之配套的 dataTemplate。

另一种解决方案是:

1-创建一个收集类别名称和汽车或人集合的类

2-为这个类创建一个dataTemplate(一个显示类别名称的文本块和一个显示带有适当dataTemplate的集合的树视图)

3-您的孩子列表将是该对象的列表。

于 2013-08-14T09:53:03.810 回答