【问题标题】:Simple Nested TreeView Xaml structure?简单的嵌套 TreeView Xaml 结构?
【发布时间】:2015-05-13 15:39:54
【问题描述】:

我正在尝试构建一个具有三层的 WPF TreeViewCountryReportTitle 是一个字符串属性,ArticleCategoryTitlesList 是一个集合,两者都暴露于我的ViewModel。没有定义类层次结构。这是我正在寻找的结构:

这是我尝试的 Xaml,但我在运行时在 Xaml 中遇到异常:

{"Item has already been added. Key in dictionary: 'DataTemplateKey(ISESApp.ViewModels.ReportViewModel)'  Key being added: 'DataTemplateKey(ISESApp.ViewModels.ReportViewModel)'"}

Xaml:

       <TreeView ItemsSource="{Binding CountryReportTitle}">
                    <TreeView ItemsSource="{Binding CountryReportTitle}">
                        <TreeView.Resources>
                            <HierarchicalDataTemplate  DataType="{x:Type local:ReportViewModel}"
                                ItemsSource="{Binding ArticleCategoryTitlesList}">
                                <TextBlock Text="{Binding CategoryTitle}" />
                            </HierarchicalDataTemplate>
                            <HierarchicalDataTemplate  DataType="{x:Type local:ReportViewModel}"
                                ItemsSource="{Binding ArticleCatagoryTypesList}">
                                <TextBlock Text="{Binding ArticleTitle}" />
                            </HierarchicalDataTemplate>
                            <DataTemplate  DataType="{x:Type local:ReportViewModel}">
                                <TextBlock Text="{Binding ArticleTitle}" />
                            </DataTemplate>
                        </TreeView.Resources>
                    </TreeView>
                </TreeView>

Local: 是我的 ViewModel 的命名空间:

xmlns:local="clr-namespace:MyApp.ViewModels"

我做错了什么,解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: c# wpf xaml mvvm treeview


    【解决方案1】:

    这是树视图的首选示例。

    对树中的元素使用HierarchicalDataTemplate。请注意,共有三层,每一层都有自己的类型。这是为了方便起见,但您可以为树定义一种类型并使用一个模板或任何类型的组合。不同的类型代表树中的不同事物,使用模板非常方便。

    数据类

    public class ViewModel
    {
        public ObservableCollection<ItemA> ItemsA { get; set; }
        public ViewModel()
        {
            ItemsA = new ObservableCollection<ItemA>(new[]{
                new ItemA{Name = "A one"},
                new ItemA{Name = "A Two"},
                new ItemA{Name = "A Three"},
            });
        }
    }
    
    public class ItemA
    {
        public ObservableCollection<ItemB> ItemsB { get; set; }
        public string Name { get; set; }
        public ItemA()
        {
            ItemsB = new ObservableCollection<ItemB>(new[]{
                new ItemB{Name = "B one"},
                new ItemB{Name = "B Two"},
                new ItemB{Name = "B Three"},
            });
        }
    }
    public class ItemB
    {
        public ObservableCollection<ItemC> ItemsC { get; set; }
        public string Name { get; set; }
        public ItemB()
        {
            ItemsC = new ObservableCollection<ItemC>(new[]{
                new ItemC{Name = "C one"},
                new ItemC{Name = "C Two"},
                new ItemC{Name = "C Three"},
            });
        }
    }
    public class ItemC
    {
        public string Name { get; set; }
    }
    

    还有用户界面

     <TreeView ItemsSource="{Binding ItemsA}">
        <TreeView.Resources>
            <HierarchicalDataTemplate  DataType="{x:Type t:ItemA}"
                                        ItemsSource="{Binding ItemsB}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate  DataType="{x:Type t:ItemB}"
                                        ItemsSource="{Binding ItemsC}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
            <DataTemplate  DataType="{x:Type t:ItemC}">
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
    

    给你一个简单的树视图

    【讨论】:

    • 谢谢。我的两个收藏都在同一个 viewModel 中。我真的不想分成不同的班级。如果是这样,我将如何定义 DataType?
    • @Hardgraf 假设 ItemsB 在 ViewModel 上而不是在 ItemA 中。您必须为 ItemA 绑定回 HierarchicalDataTemplate 中的 ViewModel--ItemsSource="{Binding DataContext.ItemsB, ElementName=root}",确保为您的 Window 提供x:Name="root",以便 ElementName 指向正确的位置。
    • 觉得我快到了。将问题更改为我的新 Xaml,但仍不确定如何为我的每个 HierarchicalDataTemplates 引用正确的 DataTypes。
    • @Hardgraf 我不知道。从你的问题中不清楚发生了什么。你说事情是错的,但你没有提供关于它是如何出错的信息,如果有错误,等等。
    • 公平点。我当前的代码在问题中。问题是直到运行时我才知道每个列表将包含什么,因此 TreeView 需要在运行时动态构建。我认为我的问题是我设置 DataType- DataType="{x:Type local:ReportViewModel}" 我不认为这是正确的,但我不确定如何将每个 HierarchicalDataTemplate 绑定到正确的列表中视图模型
    【解决方案2】:

    您需要在 TreeView 中绑定 TreeView 资源:

    <TreeView.Resources>
        <HierarchicalDataTemplate
            DataType="{x:Type local:FirstLayer}"
            ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal" Margin="2">
                <TextBlock Text="{Binding ChildrenName}" />
            </StackPanel>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate
            DataType="{x:Type local:SecondLayer}"
            ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal" Margin="2">
                <TextBlock Text="{Binding ChildrenName}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
    

    我认为您需要修改项目以将 Treeview 与 ViewModel 绑定,而不是字符串列表

    这是一个很好的Example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 2013-10-27
      • 1970-01-01
      • 2012-07-08
      • 2018-05-05
      • 1970-01-01
      相关资源
      最近更新 更多