混合类型的 WPF Treeview 数据绑定层次数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3673173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:06:29  来源:igfitidea点击:

WPF Treeview Databinding Hierarchal Data with mixed types

wpftreeviewbindinghierarchical-datahierarchicaldatatemplate

提问by thorkia

I have a bit of a complex situation with WPF Treeview Binding. I have spent the last 2 days trying Google it, and thisis the closed I came up with, but it doesn't solve the issue.

我对 WPF 树视图绑定有一些复杂的情况。过去 2 天我一直在尝试谷歌,是我想出的封闭方法,但它没有解决问题。

Here is the situation:

这是情况:

I have an object that looks like this:

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

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

Each Category can have a list of objects, and child categories. I have a reason for doing this that makes complete sense to me, and the app I am writing.

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

The actual object construction may look Something like this:

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

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

Now, I am trying to databind this relationship to a treeview. I would like the TreeView to look almost identical to the above object construct.

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

So far I have my XAML Treeview look like this:

到目前为止,我的 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>

This works great for the main list of Categories, and each of it's sub products. But it doesn't go deeper and display the sub categories under each category.

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

Is there any way to do this directly with Templates so that each item (category or product) is selected? I am using an MVVM pattern and don't want to resort to using the code behind, but will if it is necessary.

有没有办法直接使用模板来做到这一点,以便选择每个项目(类别或产品)?我正在使用 MVVM 模式并且不想诉诸于使用背后的代码,但如果有必要的话。

回答by Quartermeister

Since you want the elements in the TreeView to have a list of children that consists of both Categories Products, you will want your Category ViewModel to have a collection that consists of both Categories and Products. For example, you could use a CompositeCollectionto combine your existing collections:

由于您希望 TreeView 中的元素具有包含两个类别产品的子项列表,因此您希望类别视图模型具有包含类别和产品的集合。例如,您可以使用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 }
            };
        }
    }
}

(In real code, you would probably want to keep a reference to the same collection object rather than creating a new one each time.)

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

Then in your HierarchicalDataTemplate, use the combined list as the ItemsSource:

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

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

The items will be a mix of Product and Category objects, and WPF will use the appropriate DataTemplate for each one.

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