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,例如:
- 模板名称A
模板名称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有问题,也许我应该有另一个层次数据模板?
在这种情况下,最好、最通用的(在我看来)解决方案是为树中显示的每种类型的项定义一个模板,并将它们放入树的资源字典中。每个模板都应该使用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的根元素(通常是Window
或UserControl
)上定义命名空间映射是常见的做法。请在此处查看更多信息:WPF XAML的XAML命名空间和命名空间映射。
请注意,尽管模板被放在资源字典中,但并没有指定x:Key
参数。在自动模板选择过程中需要考虑模板。这类模板被称为隐式模板。这里有一个有用的链接:数据模板概述。