WPF Treeview数据绑定分层数据与混合类型

tho*_*kia 33 wpf treeview binding hierarchicaldatatemplate hierarchical-data

我对WPF Treeview Binding有一些复杂的情况.我花了最近两天的时间尝试谷歌,是我提出的关闭,但它没有解决问题.

情况如下:

我有一个看起来像这样的对象:

public class Category
{
  public string Name { get; set; }
  public List<Category> Categories { get; set; }
  public List<Product> Products { get; set; }
}

public class Product
{
  public string Name { get; set;
}
Run Code Online (Sandbox Code Playgroud)

每个类别都可以包含对象列表和子类别.我有理由这样做对我和我正在写的应用程序完全有意义.

实际的对象构造可能看起来像这样:

Category - Pharmacy
  |-Product - Aspirin
  |-Product - Tylenol
  |-Category - Tooth Paste
  |  |-Product - Crest
  |  |-Product - Colgate
  |-Category - Paper Products
   |-Category - Toilet Paper
   |  |-Product - NoName
   |  |-Product - Charmin
   |-Category - Facial Tissue
      |-Product - Kleenex
Category - Household
  |-Product - Pinesol Cleaner
  |-Product - Garbage Bags
Run Code Online (Sandbox Code Playgroud)

现在,我正在尝试将此关系数据绑定到树视图.我希望TreeView看起来与上面的对象构造几乎相同.

到目前为止,我的XAML Treeview看起来像这样:

  <TreeView x:Name="CategoryList" Margin="8" Grid.Row="2" Grid.RowSpan="2" ItemsSource="{Binding Path=Categories}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type src:Category}" ItemsSource="{Binding Products}">
                    <StackPanel>
                        <TextBlock Text="{Binding Path=Name}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type src:Product}">
                    <StackPanel>
                        <TextBlock Text="{Binding Path=Name}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
Run Code Online (Sandbox Code Playgroud)

这适用于类别的主要列表及其每个子产品.但它并没有更深入地显示每个类别下的子类别.

有没有办法直接使用模板执行此操作,以便选择每个项目(类别或产品)?我正在使用MVVM模式,并且不想使用后面的代码,但是如果有必要的话.

Qua*_*ter 54

由于您希望TreeView中的元素包含由两个类别产品组成的子项列表,因此您希望类别ViewModel具有包含类别和产品的集合.例如,您可以使用CompositeCollection来组合现有集合:

public class Category
{
    public string Name { get; set; }
    public List<Category> Categories { get; set; }
    public List<Product> Products { get; set; }

    public IList Children
    {
        get
        {
            return new CompositeCollection()
            {
                new CollectionContainer() { Collection = Products },
                new CollectionContainer() { Collection = Categories }
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(在实际代码中,您可能希望保留对同一集合对象的引用,而不是每次都创建一个新集合对象.)

然后在HierarchicalDataTemplate中,使用组合列表作为ItemsSource:

<HierarchicalDataTemplate DataType="{x:Type src:Category}"
                          ItemsSource="{Binding Children}">
Run Code Online (Sandbox Code Playgroud)

这些项目将是Product和Category对象的混合,WPF将为每个对象使用适当的DataTemplate.

  • 这是一个完美的解决方案,谢谢!就像其他人的注释一样,将集合容器添加到复合集合的顺序是它们在树视图中显示的顺序.如果您首先添加类别,它们将出现在产品之前 (3认同)