0

今天最后一个问题。

我是 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 的构造函数,它检索被点击的人的 Person Model 数据。完美运行,我可以通过绑定显示第一级数据,例如人名:{Binding Path=ClickedPerson.Name}

我的问题是:我怎样才能有一个 ItemsControl 来显示那个人的数据的第 2 级和第 3 级?意思是,如果我要实现一个 ItemsControl,其中将有一个带有 1 个新 UserControl(例如)的堆栈面板,用于该人生活中的每个 OldJob,然后让该 UserControl 的子控件反映该旧工作的特定数据,例如文本框中的职业或薪水=> 如何在 XAML 中编写绑定部分?

不用担心 UI,我可以处理,这只是我不确定的 Binding 部分。

如果我像盲人大猩猩一样解释它,请告诉我...

更新:按照你们所说的,我编写了下面的简单 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

4 回答 4

0

您可以在DataGrid此处将 List ofPerson作为其ItemsSource. 一旦你这样做了,每个 DataGridRow 都会有一个对象Person作为它的DataContext. 现在您可以将列DataGrid绑定到Person.

接下来,您可以定义RowDetailsTemplate以显示分层数据。您可以将行模板设置为DataGrid再次显示其中的作业。至于DataContext这个数据网格也将是 Person 对象,您可以绑定到 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>

谢谢

于 2013-09-06T11:41:42.210 回答
0

我有一个例子,我有像你一样的东西,但是使用 Buttongroups 和 Buttons(而不是你的 Jobs 和 Job1,Job2,......所以在我的 ViewModel 中我有一个属性 ObservableCollection<ButtonGroups> Groups。我的 ButtonGroups-Model 有一个字符串 GroupName 和一个带有按钮的 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>

它给了我一排我定义的按钮。所以我为每个按钮有 1 个 ItemsControl。您可以修改您的 ItemsControl 以拥有您的作业和要显示的每个作业的属性。

这是我的问题,我从哪里得到的:链接

希望对您有所帮助。

于 2013-09-06T11:40:52.363 回答
0

您可以使用 WPF 的 TreeView。HierarchialDataTemplate会在这里帮助你。

对于一个简单的例子,请参阅 MSDN在此处输入链接描述

 <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。

于 2013-09-06T11:30:37.760 回答
0

这不是 MVVM 问题,而是Binding路径语法问题。因此,您可能希望查看 MSDN 上的Binding.Path 属性页面。

从链接页面:

当源是集合视图时,可以用斜杠 (/) 指定当前项。例如,子句 Path=/ 将绑定设置为视图中的当前项。当源是集合时,此语法指定默认集合视图的当前项。

基本上,这意味着您可以使用以下内容Binding显示OccupationselectedJob中的 selected Person

{Binding PersonCollection/JobCollection/Occupation}
于 2013-09-06T11:31:41.653 回答