我正在尝试从ImpactElement对象获取信息的WPF项目。该对象位于名为ElementList的ObservableCollection中。这个ElementList位于另一个名为ListOfCreatedStacks的ObservableCollection中,它保存了Class Stack的对象。
它只显示ElementList中元素(ImpactElement)的toString。我希望从ElementList中的每个元素显示ImpactElements变量ElementMark。
这就是它现在的样子One element added in the ElementList
我可以创建任意数量的Stack,并且在每个堆栈中都有一个具有不同数量的ImpactElement的ElementList。 Two stacks with different amount of ImpactElements in the ElementList
从这些图片中可以看到ElementList中的每个ImpactElement都显示为“IMPACT_Visual_Stacker.Model.ImpactElement”,但我希望它是ImpactElement Class中的变量ElementMark。
以下是来自不同类的代码。
public class Controller
{
public ObservableCollection<Stack> ListOfCreatedStacks { get { return listOfCreatedStacks; } set { listOfCreatedStacks = value; } }
}
public class Stack
{
public ObservableCollection<ImpactElement> ElementList { get { return elementList; } set { elementList = value; } }
public string Id { get { return id; } set { id = value; } }
}
public class ImpactElement
{
private string elementMark;
private int id;
private Vector3 sizeLWH;
private Vector3 positionXYZ;
private Vector3 rotationXYZ;
private Mesh elementMesh;
}
这是XAML部分。
<ListView ItemsSource="{Binding ListOfCreatedStacks}" HorizontalAlignment="Left" Margin="350, 200,0,0" Width="300">
<ListView.ItemTemplate>
<DataTemplate>
<TreeViewItem
Header="{Binding Id}"
IsExpanded="True">
<TreeViewItem
ItemsSource="{Binding ElementList}" Header="{Binding ElementMark}" IsExpanded="True">
</TreeViewItem>
</TreeViewItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我尝试过从Ed获得的其他StackOverflow的解决方案。 结果最终只添加了我的“ImpactElement”对象的Hiearchy对象。
这是经过测试的XAML的样子:
<ListView ItemsSource="{Binding ListOfCreatedStacks}" HorizontalAlignment="Left" Margin="350, 200,0,0" Width="300">
<ListView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type System:String}"
ItemsSource="{Binding ListOfCreatedStacks}">
<TreeViewItem
Header="{Binding Id}"
IsExpanded="True">
<HierarchicalDataTemplate DataType="{x:Type System:String}"
ItemsSource="{Binding ElementList}">
<TreeViewItem
Header="{Binding ElementMark}"
IsExpanded="True">
</TreeViewItem>
</HierarchicalDataTemplate>
</TreeViewItem>
</HierarchicalDataTemplate>
</ListView.ItemTemplate>
</ListView>
感觉就像想念一些我不理解的简单部分。谢谢你的帮助。
答案 0 :(得分:0)
首先,Controller
,ElementList
和ImpactElement
可能应该实施INotifyPropertyChanged
。你可以在Stack Overflow和其他地方找到一百万个这样的例子。这很简单,如果遇到任何障碍,你可以在这里获得帮助。
如果您在UI中看到这些对象时更改了这些对象的任何绑定属性值,那么它将会导致UI更新。如果您添加或删除项目,ObservableCollection
将通知用户界面,但如果其中一个项目的某些属性发生变化,则无法通知用户界面。
其次,ImpactElement
只有私有字段。由于私有字段在其他类中被省略,我猜这只是在复制代码时的疏忽。但是你只能绑定到公共属性。必须是公开的,必须是get
且通常为set
的媒体资源。
我希望您已为Controller
分配了DataContext
的实例。如果你没有,树将不会填充。
我首先发现WPF的TreeView
令人费解,当我第一次看到它时,我并不是XAML的新手。做一堆简单的例子(如果你需要的话,来这里寻求帮助),不要只粘贴我给你的XAML。它会成为焦点。
最后,您在XAML中做了很多未在示例中完成的事情。我不知道你为什么要做那些事情,但你不能随意做些事情。它不能很好地工作。但正如我所说,这个问题的学习曲线很难,所以没有伤害。
所以这是XAML:
<TreeView
ItemsSource="{Binding ListOfCreatedStacks}"
HorizontalAlignment="Left"
Margin="350, 200,0,0"
Width="300">
<TreeView.ItemContainerStyle>
<Style
TargetType="TreeViewItem"
BasedOn="{StaticResource {x:Type TreeViewItem}}"
>
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:Stack}"
ItemsSource="{Binding ElementList}"
>
<Label Content="{Binding Id}" />
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:ImpactElement}"
>
<Label Content="{Binding ElementMark}" />
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
因此TreeView的ItemsSource是ListOfCreatedStacks
。
我们为TreeView
提供ItemContainerStyle
,它将适用于树中的每个TreeViewItem
。我们只这样做,所以我们可以设置IsExpanded
。没有其他方法可以到达TreeViewItem
。我们可以也为顶级项目模板提供自己的ItemContainerStyle
,如果我们想要做一些与之不同的事情,这只会影响其子项。但我们不需要。
我们给TreeView
ItemTemplate
。这就是我们如何显示TreeViewItem
如何显示其中一个TreeView
的孩子。当您查看HierarchicalDataTemplate
时,它有点像TreeView
:它有ItemsSource
,我们绑定到包含子项的Stack
属性<{1}}的。它有自己的孩子Stack
。正如我所说,可以有一个ItemTemplate
,但我们只是让它继承我们在ItemContainerStyle
上设置的那个。
它是递归的:树节点非常像整棵树。
如果你没有给自己TreeView
HierarchicalDataTemplate
,那么它适用的ItemTemplate
只会使用那个作为自己孩子和孩子的模板也会这样做。如果你给TreeViewItems
ImpactElement
个ImpactElement
个子集合,那么这个树可能有二十几个级别而不会在上面的XAML中进行一次更改。
任何DataTemplate
或HierarchicalDataTempate
都可以拥有DataType
属性。这是模板显示的viewmodel项的类型。我不知道你从哪里来System:String
。
在这个特殊情况下 1 ,DataType
没有任何意义,只是为了帮助你在编辑XAML时保持正确:它会提醒你哪个模板的递归级别适用收集项目,他的Intellisense也帮助你。
最后,我们有HierarchicalDataTempate
的内容:
<Label Content="{Binding Id}" />
这可以是任何单个XAML元素,但如果您需要,它可以是包含整个UI的Grid
或StackPanel
。你可以放任何东西。你可以在那里放一个完全不同的TreeView
。
最后,您应该学会使用StackPanel
和Grid
列和行进行布局。如果你想重新排列任何东西,这个保证金业务是一场噩梦。我假设你在VS中使用设计模式?我所用的就是预览我在XAML中手工完成的工作。正确完成,在XAML布局中,所有内容都相对于其父节点和兄弟节点定位。也许它有一个固定的宽度和/或高度,通常是一个小的边距 - 单个数字 - 只是为了在邻居之间创造空间,而不是绝对定位。一旦你习惯了它,这是一个非常好的方式来处理东西。很像HTML。
1 对于DataType
或DataTemplate
的{{1}}属性的其他用途,请参阅"implicit datatemplates",此处为{{3} }}。如果你已经在努力消化所有这些,不要去看那些东西,只关注我上面给你的情况。这绰绰有余。数据模板是一种学习曲线,添加递归只会让所有东西更加怪异。