如何使用字典和嵌套列表为 TreeView 编写 XAML?

How to write XAML for TreeView with Dictionary and nested lists?

我正在为教师和学生编写一个应用程序,在该应用程序中,教师可以根据所选科目查找学生的成绩。

为了将所有内容组合在一起,我创建了一个字典,其中包含所选科目的所有学生成绩(例如,数学的所有成绩,这里并不重要):

IDictionary<Class, List<KeyValuePair<Student, List<Grade>>>>

Class是这本词典的关键字,就是学生所属的class。它有一个我想显示的字符串类型的名称(例如“4F”)

Value 是一个列表,其中包含来自给定 class 的 Students 和 his/her Grades 的列表(每个等级都有值和描述,例如 3- 和 "Algebra exam",我也想展示它们)。

基本上我希望看​​到的每个 Class(这意味着字典中的每个键)是这样的(学生人数和成绩可能会有所不同):

我一直在寻找解决方案,我认为它可能涉及使用 <TreeView.Resources><HierarchicalDataTemplate>,但老实说我不太了解如何使用它们。我尝试了一种解决方案,但只显示了与 class 连接的每个 ClassName 和 Students,但无法显示任何其他内容。此处建议的另一个解决方案: 给我留下了:

[SchoolerDatabaseUtilities.Class,System.Collections.Generic.List'1[System.Collections.Generic.KeyValuePair'2[SchoolerDatabaseUtilities.Student,System.Collections.Generic.List'1[SchoolerDatabaseUtilities.Grade]]]] 

为我在字典中的每个键编写(SchoolerDatabaseUtilities 只是一个库,我使用它来保持文件中的所有内容干净)。

请帮我解决任何问题,因为我什至不知道从哪里开始...

有人建议我的问题与 WPF TreeView hierarchical binding. 重复,但对我来说似乎不是。我使用的是 Dictionary,而不是 List<>(),在我看来,我的问题本质上有点难(无论我解决问题的方法在术语还是可读性方面是否良好)。

您将 have.to 使用 HierarchicalDataTemplate

但是您应该尝试重新设计并构建您的类型以明确反映树数据结构 - 没有嵌套集合。这意味着 Class 应该有一个类型为 Student 的子集合,Student 应该有一个类型为 Grade 的子集合。然后 ClassClass 的集合将成为树的根(整个 TreeViewItemsSource 绑定源)。如果您这样做了,那么模板可以设置 DataType 属性,这将使所有类型转换变得多余。使用起来也更方便并提高了可读性。

<TreeView ItemsSource="{Binding TreeSource}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Value}">
      <TextBlock Text="{Binding Key.(Class.Name)}" />

      <HierarchicalDataTemplate.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Value}">
          <TextBlock Text="{Binding Key.(Student.Name)}" />

          <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate DataType="Grade">
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Value}" />
                <TextBlock Text="{Binding Description}" />
              </StackPanel>
            </DataTemplate>
          </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
      </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

我跟着 BionicCode's advice and Microsoft Docs 做了 List<Class>,其中每个 Class 都有 List<Student>,每个学生都有 List<Grade>,这让一切变得更好更容易。
毕竟我的代码是这样的:

<TreeView ItemsSource="{Binding MyListOfClasses}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type utilities:Class}" ItemsSource="{Binding StudentList}">
               <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type utilities:Student}" ItemsSource="{Binding GradesList}">
               <TextBlock Text="{Binding FullNameRev}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type utilities:Grade}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="75" />
                    <ColumnDefinition Width="500" />
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Value}" Grid.Column="0"/>
                <TextBlock Text="{Binding Description}" Grid.Column="1"/>

            </Grid>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

其中实用程序在我的 <UserControl> 标记中定义为:

xmlns:utilities="clr-namespace:SchoolerDatabaseUtilities;assembly=SchoolerDatabaseUtilities"

SchoolerDatabaseUtilities 是我的图书馆,其中定义了所有这些 类