WPF、TreeView、绑定到集合中对象内部的属性

本文关键字:对象 内部 属性 集合 TreeView 绑定 WPF | 更新日期: 2023-09-27 18:28:35

这可能并不难,但我越来越困惑了。

我想在我的视图中显示TreeView,但我无法获得正确的数据绑定。

TemplateFamilyList集合是根对象。它将包含TemplateFamily对象的列表。每个TemplateFamily对象都将包含一个Template对象和一个名为TemplateParameterMembers的TemplateParameter对象列表。在其他属性中,实际的Template类和实际的TemplateParameter类都具有Name属性。

因此,在我的ViewModel类中,我有一个填充集合的方法:

 public void LoadTemplateTree()
    {
        TemplateFamilyList = new ObservableCollection<TemplateFamily>();
        List<Template> templateList = BuilderService.GetAllTemplates();
        List<TemplateParameter> templatesParametersList;
        foreach (Template template in templateList)
        {
            templatesParametersList = BuilderService.GetATemplatesParameters(template.TemplateID);
            TemplateFamilyList.Add(new TemplateFamily(template, new ObservableCollection<TemplateParameter>(templatesParametersList)));              
        }
    }

这是圣殿家族类:

 public class TemplateFamily
{
    public Template Template { get; set; }
    public ObservableCollection<TemplateParameter> TemplateParameterMembers { get; set; }
    public TemplateFamily(Template aTemplate, ObservableCollection<TemplateParameter> templatesParameters)
    {
        Template = aTemplate;
        TemplateParameterMembers = templatesParameters;
    }
}

我想要的是TreeView,例如:

  1. 模板名称A
  2. 模板名称B

    • 模板参数名称B1
    • 模板参数名称B2

等等。

在我的XAML中,我有这样的:(但它不起作用,它给出了一些只有箭头但没有名称的空白树视图)。

<TabItem Header="Template Files" Height="22" VerticalAlignment="Top">
            <TreeView Height="Auto" Name="treeView1" Width="Auto" ItemsSource="{Binding TemplateFamilyList}">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding TemplateParameterMembers}" >
                        <TextBlock Text="{Binding Path=Name}" Margin="2" ></TextBlock>
                    </HierarchicalDataTemplate >
                </TreeView.ItemTemplate>
            </TreeView>
        </TabItem>

ViewModel通过ViewModelLocator绑定到视图,在其他情况下也可以正常工作。我知道,如果我绑定到TemplateFamilyList,它会得到正确的对象,我只是不知道如何显示该列表中每个TemplateFamily的名称(应该是TemplateFamily对象的Template属性的name属性),然后在树中的下一个级别(如果有TemplateParameterMembers的列表),如何显示TemplateParameterMembers集合中每个项的TemplateParameter属性的Name属性。

我想我可以尝试在TemplateFamily类中使用另一个属性Name,并简单地在构造函数中复制Template的Name属性,例如:

public TemplateFamily(Template aTemplate, ObservableCollection<TemplateParameter> templatesParameters)
    {
        Template = aTemplate;
        Name = aTemplate.Name;
        TemplateParameterMembers = templatesParameters;
    }

但我不喜欢这种方法,此外,我没有用于TemplateParameters集合的特殊"容器"类,所以我仍然需要以某种方式深入并获取TemplateParameterMembers集合的每个项中TemplateParameter的Name属性。

我看到这个帖子了在答案中,Gishu似乎使用了DataType属性,例如:

DataType="{x:Type local:Group}

OP帖子中定义的本地命名空间为:

xmlns:local="clr-namespace:TaskManager.Domain;assembly=TaskManager.Domain"

但是,在我的情况下,Template和TemplateParameter类是我的模型的一部分,它们甚至与ViewModel和View不在同一个项目中。就我的本地命名空间而言:

xmlns:local="clr-namespace:S.VisualStudioExtension"           
         local:ViewModelLocator.AutoWireViewModel="True"

然后我是否应该为Template和TemplateParameter类添加一个名称空间,例如:

xmlns:domain="clr-namespace:S.ModelDomain" 

并尝试在DataType属性中使用它?

我还怀疑我的XAML有问题,也许我应该有另一个层次数据模板?

WPF、TreeView、绑定到集合中对象内部的属性

在这种情况下,最好、最通用的(在我看来)解决方案是为树中显示的每种类型的项定义一个模板,并将它们放入树的资源字典中。每个模板都应该使用DataType属性与相应的项目类型相关联。这样,将自动选择合适的模板,根据其类型呈现每个项目。假设您的TemplateParameter类是在命名空间S.ModelDomain中名为S.ModelDomain的项目中定义的,并且local前缀在XAML中正确定义,这应该会给您带来预期的结果(我冒昧地剥离了XAML中不相关的属性):

<TreeView xmlns:models="clr-namespace:S.ModelDomain;assembly=S.ModelDomain"
          ItemsSource="{Binding TemplateFamilyList}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:TemplateFamily}"
                                  ItemsSource="{Binding TemplateParameterMembers}" >
            <TextBlock Text="{Binding Template.Name}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type models:TemplateParameter}">
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

不过,在XAML的根元素(通常是WindowUserControl)上定义命名空间映射是常见的做法。请在此处查看更多信息:WPF XAML的XAML命名空间和命名空间映射。

请注意,尽管模板被放在资源字典中,但并没有指定x:Key参数。在自动模板选择过程中需要考虑模板。这类模板被称为隐式模板。这里有一个有用的链接:数据模板概述。