当天的最后一个问题。
我是MVVM建模的新手,并且在理解它的过程中已经取得了相当多的成就,但是在我通过摆弄整个项目之前我需要一些指导。
我创建了一个名为Person的模型,其中包含以下内容:
- General info like: ID, FirstName, LastName, FullName, Nationality etc.
- A list of old jobs
- Each job (a separate model) within the old jobs list has data as well such as YearStarted, YearEnded, Occupation, Company etc.
所以我的模型看起来像这样:
- Person:
- ID
- Name
- Nationality
- Jobs:
- Job1:
- Occupation
- Started
- Ended
- Salary
- Duties:
- Duties 1
- Duties 2
- Job2:
- Occupation
- Started
- Ended
- Salary
- Duties:
- Duties 1
- Duties 2
- Duties 3
在我看来,人物清单显示完美。当我点击其中一个人时,我正在用自己的控件打开一个新的WPF页面。我已经设置了一个名为ClickedPerson的构造函数,用于检索单击的人员的人员模型数据。完美的工作,我可以显示第一级数据,如绑定人的姓名:{Binding Path = ClickedPerson.Name}
我的问题是:如何让ItemsControl显示该人数据的2级和3级?意思是,如果我要实现一个ItemsControl,其中会有一个带有1个新UserControl(例如)的堆栈面板,用于该人生活中的每个OldJob,然后让UserControl的子控件反映旧作业的特定数据,如文本框中的Occupation或Salary =>如何在XAML中编写绑定部分?
不要担心用户界面,我可以处理它,它只是我不确定的绑定部分。
如果我像盲人大猩猩一样解释它,请告诉我......
更新: 所以你们说的是,我写了下面简单的UI绑定,但它没有显示任何内容。我做错了什么?
<TreeView Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="3"
ItemsSource="{Binding Path=ClickedPerson}">
<!-- List of OldJobs teamplate -->
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Duties}">
<TextBlock Foreground="White" Text="{Binding JobNumber}" />
<!-- Job template -->
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Occupation}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
更新2: 我不是这个我?
我已经在我的ViewModel和View中根据我读过的内容以及你们所说的内容写了这个...认为它会起作用但在我的Treeview中没有显示任何内容:
private Person _clickedPerson;
public CollectionViewSource ClickedPersonJobs { get; set; }
public Person ClickedPerson
{
get { return _clickedPerson; }
set
{
_ clickedPerson = value;
ClickedPersonJobs = new CollectionViewSource();
ClickedPersonJobs.SortDescriptions.Add(new SortDescription("JobNumber", ListSortDirection.Ascending));
ClickedPersonJobs.GroupDescriptions.Add(new PropertyGroupDescription("JobNumber"));
ClickedPersonJobs.Source = _ clickedPerson.OldJobs;
NotifyOfPropertyChange(() => ClickedPerson);
}
}
并在我的View XAML文件中:
<TreeView ItemsSource="{Binding ClickedPersonJobs }"
Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="3">
<!-- Job teamplate -->
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Duties}">
<TextBlock Foreground="Red" Text="{Binding Occupation}" />
<!-- Duties template -->
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
答案 0 :(得分:0)
您可以使用WPF的TreeView。 HierarchialDataTemplate
会在这里为您提供帮助。
有关简单的例子,请参阅MSDN enter link description here
<HierarchicalDataTemplate DataType = "{x:Type src:League}"
ItemsSource = "{Binding Path=Divisions}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType = "{x:Type src:Division}"
ItemsSource = "{Binding Path=Teams}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type src:Team}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
这将显示3级层次结构。
League
Division
Team
关键是使用HierarchicalDataTemplate的ItemsSource并为每个提供正确的DataTemplate。
答案 1 :(得分:0)
这不是MVVM问题,而是Binding
路径语法问题。因此,您可能希望在MSDN上查看Binding.Path Property页面。
从链接页面:
当源是集合视图时,可以使用斜杠(/)指定当前项。例如,子句Path = /设置绑定到视图中的当前项。当源是集合时,此语法指定默认集合视图的当前项。
基本上,这意味着您可以使用以下Binding
来显示所选Occupation
中所选Job
的{{1}}:
Person
答案 2 :(得分:0)
我有一个例子,我有类似你的东西,但有Buttongroups和Buttons(而不是你的Jobs和Job1,Job2,......所以在我的ViewModel中我有一个ObservableCollection<ButtonGroups> Groups
的属性。我的ButtonGroups -Model有一个字符串GroupName和一个带Buttons的ObservableCollection,我在其中声明了LabelString和ButtonCommand。
我的ItemsControl看起来像这样:
<ItemsControl x:Name="Groups" ItemsSource="{Binding Groups}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox Header="{Binding Path=GroupName}">
<ItemsControl ItemsSource="{Binding Buttons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Path=LabelString}" Command="{Binding Path=ButtonCommand}"/>
</DataTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="BtnStackPanel" Orientation="Horizontal"/>
</ItemsPanelTemplate>
<ItemsControl.ItemsPanel>
</ItemsControl>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="GroupStackPanel" Orientation="Horizontal"/>
</ItemsPanelTemplate>
<ItemsControl.ItemsPanel>
它给了我一行我定义的按钮。所以每个Button都有1个ItemsControl。您可以修改ItemsControl以使您的作业和要显示的每个作业的属性。
这是我的问题,我得到了:Link
希望对你有所帮助。
答案 3 :(得分:0)
您可以在此处DataGrid
将Person
列表作为其ItemsSource
。完成此操作后,每个DataGridRow都将Person
的对象作为其DataContext
。现在,您可以将DataGrid
中的列绑定到Person
的属性。
接下来,您可以定义RowDetailsTemplate
以显示hierarycal数据。您可以将rowtemplate设置为再次DataGrid
以显示其中的作业。由于此数据网格的DataContext
也将是Person对象,您可以将其绑定到人员内部的JobList以填充其中的数据。类似地,您可以有多个层次结构。
<DataGrid ItemsSource="{Binding PersonList}">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding FirstName}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding LastName}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding FullName}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Jobs}">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Occupation}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Started}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Salary}"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
由于