在多个级别上进行数据绑定

时间:2013-09-06 11:22:39

标签: c# wpf xaml data-binding mvvm

当天的最后一个问题。

我是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>

4 个答案:

答案 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)

您可以在此处DataGridPerson列表作为其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>

由于