WPF树形视图中混合类型层次数据的数据绑定

40

我在WPF Treeview绑定方面遇到了一些复杂的情况。我已经花了最近2天的时间试图在Google上搜索,这个是我找到的最接近的答案,但它并没有解决我的问题。

以下是具体情况:

我有一个像这样的对象:

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;
}
每个类别可以有一系列对象及子类别。我做这样的设计是有我的理由,而且对于我正在编写的应用程序来说也是十分合理的。

实际对象的构建可能看起来像这样:
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

现在,我正在尝试将这个关系数据绑定到一个树视图。我希望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>

这对于主要的分类列表和每个子产品都非常有效。但是它没有更深入地显示每个类别下面的子类别。

是否有直接使用模板实现每个项(类别或产品)被选中来完成此操作的方法?我正在使用MVVM模式,不想诉诸于使用代码后台,但如果必要的话,我会这样做。

1个回答

61

由于您希望TreeView中的元素具有包含类别产品的子列表,因此您需要让Category 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 }
            };
        }
    }
}

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

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

<HierarchicalDataTemplate DataType="{x:Type src:Category}"
                          ItemsSource="{Binding Children}">

这些项将是产品和类别对象的混合,WPF将为每个对象使用适当的数据模板。


4
这是一个完美的解决方案,谢谢!顺便提醒其他人一下,您将集合容器添加到组合集合中的顺序,会影响它们在树形视图中的显示顺序。如果您先添加分类,它们会出现在产品之前。 - thorkia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接