首页 > 解决方案 > 在 WPF 中将多个 TreeViews 显示为 TreeViewItems 列表的 ObservableCollection

问题描述

由于每个帖子我只能问一个问题,我会在这里再试一次。

我尽量简单地解释我的问题。我想加载一个 KML 文件并将其结构显示为 TreeView。异步加载方法使用根节点和子节点填充整个 TreeView。

如果我只加载 1 个 KML 文件,它就可以正常工作。但如果可能,我想加载多个 KML 文件并将整个结构显示为 TreeViews 列表。

我的 View.xaml 看起来像这样:

<ListView ItemsSource="{Binding TreeViews}">
            <ListView.ItemTemplate>
                <HierarchicalDataTemplate>
                    <TreeView Name="TreeView" MaxHeight="300" SelectedItemChanged="TreeView_SelectedItemChanged" ItemsSource="{Binding TreeViewItems}">
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsExpanded" Value="True"/>
                            </Style>
                        </TreeView.ItemContainerStyle>
                        <TreeView.ItemTemplate>
                            <HierarchicalDataTemplate DataType="{x:Type local:TreeViewItem}" ItemsSource="{Binding ChildrenItems}">
                                <StackPanel Orientation="Horizontal">
                                    <CheckBox Focusable="False" IsChecked="{Binding IsChecked}"/>
                                    <ContentPresenter Margin="2,0,0,0" Content="{Binding NodeName, Mode=OneTime}"/>
                                </StackPanel>
                            </HierarchicalDataTemplate>
                        </TreeView.ItemTemplate>
                    </TreeView>
                </HierarchicalDataTemplate>
            </ListView.ItemTemplate>
</ListView>

在我的 ViewModel 中,我有两个属性:

public ObservableCollection<List<TreeViewItem>> TreeViews { get; set; }

private List<TreeViewItem> treeViewItems;
public List<TreeViewItem> TreeViewItems
{
    get { return treeViewItems; }
    set
    {
        treeViewItems = value;
        OnPropertyChanged();
    }
}

出于测试目的,我只是在 load 方法中添加了一些项目:

List<TreeViewItem>  temp = new List<TreeViewItem>();

TreeViewItem rootItem = new TreeViewItem(null, null);
TreeViewItem ChildItem1 = new TreeViewItem(null, null);
TreeViewItem ChildItem2 = new TreeViewItem(null, null);

rootItem.ChildrenItems.Add(ChildItem1);
rootItem.ChildrenItems.Add(ChildItem2);

temp.Add(rootItem);

TreeViewItems = temp;

TreeViews.Add(TreeViewItems);
TreeViews.Add(TreeViewItems);

现在它应该在视图中显示 2 个相同的 TreeView。但不幸的是,它只显示了 2 个带有 CheckBox 的空列表项。

有没有人提示我如何显示多个 TreeView?

标签: c#wpfxamltreeview

解决方案


您的问题目前没有多大意义 - 为什么您认为您需要 TreeViews 中的 TreeViews 来处理这种分层数据结构?是什么local:TreeViewItem以及它有什么不同System.Windows.Controls.TreeViewItem

最好将数据结构与可视控件分开。像这样,在 TreeView 中显示的每个级别的项目都有不同的类。

public class KLMFile
{
    public string FileName {get; set;}
    ...
    public List<KLMItem> Children {get;} = new List<KLMItem>();
}

public class KLMItem
{
    public string Description {get;set;}
    ...
    public List<KLMSubItem> Children {get;} = new List<KLMSubItem>();  
}

public class KLMSubItem
{
    public string Description {get;set;}
    ...
    // top level items - no children
} 

分配(或绑定)一组 KLMFile 项作为ItemsSourceTreeView 控件的属性。

为 TreeView 中的每个项目类型创建一个HierarchicalDataTemplate(或DataTemplate没有更多子项的最高级别项目的纯文本)。

<TreeView ItemsSource="{Binding KLMFileList}">
    <TreeView.Resources>
        <HierarchicalDataTemplate
            DataType="{x:Type local:KLMFile}"
            ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding FileName}" />
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate
            DataType="{x:Type local:KLMItem}"
            ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Description}" />
        </HierarchicalDataTemplate>

        <DataTemplate
            DataType="{x:Type local:KLMSubItem}">
            <TextBlock Text="{Binding Description}" />
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

有关 WPF TreeViews 的更多详细信息(但更侧重于在 MVVM 设计模式中使用它们),请参阅我的博客文章


推荐阅读