WPF MVVM实现TreeView层级显示

最近在写一个小工具的时候,遇到TreeView的层级显示,刚好我又用了MVVM模式,所以这里做个总结。

以前我是直接绑定XML数据到TreeView的,使用的XmlDataProvider,这次的数据是直接来自数据库的。

用到的都是HierarchicalDataTemplate

下面演示一下如何使用绑定实现TreeView的层级显示

1.创建一个ViewModelBase类,实现INotifyPropertyChanged

复制代码
1   public class ViewModelBase : INotifyPropertyChanged
2     {
3         public event PropertyChangedEventHandler PropertyChanged;
4 
5         public void RaiseChange(string propertyName)
6         {
7             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
8         }
9     }

2.创建模型

这里我建立 了三个层级 的数据

层级1 包含了一个属性一个层级2列表

层级2 包含了一个属性一个层级3列表

层级3 包含了一个属性

在构造函数中创建测试数据

cs 复制代码
namespace MVVMTreeViewHierarchical
{
    public class Level1 : ViewModelBase
    {
        private string level1Item = "";

        public string Level1Item
        {
            get => level1Item;
            set
            {
                level1Item = value;
                RaiseChange("Level1Item");
            }
        }

        private List<Level2> level1ChildList = new List<Level2>();

        public List<Level2> Level1ChildList
        {
            get => level1ChildList;
            set
            {
                level1ChildList = value;
                RaiseChange("Level1ChildList");
            }
        }

        public Level1(string item)
        {
            //构建测试数据
            level1Item = item;
            for(int i = 0;i<3;i++)
            {
                level1ChildList.Add(new Level2($"层级2项目@{i}"));
            }
        }
    }

    public class Level2 : ViewModelBase
    {
        private string level2Item = "";

        public string Level2Item
        {
            get => level2Item;
            set
            {
                level2Item = value;
                RaiseChange("Level2Item");
            }
        }

        private List<Level3> level2ChildList = new List<Level3>();

        public List<Level3> Level2ChildList
        {
            get => level2ChildList;
            set
            {
                level2ChildList = value;
                RaiseChange("Level2ChildList");
            }
        }

        public Level2(string item)
        {
            //构建测试数据
            level2Item = item;
            for (int i = 0; i < 3; i++)
            {
                level2ChildList.Add(new Level3($"层级3项目@{i}"));
            }
        }
    }

    public class Level3 : ViewModelBase
    {
        private string level3Item = "";

        public string Level3Item
        {
            get => level3Item;
            set
            {
                level3Item = value;
                RaiseChange("Level3Item");
            }
        }

        public Level3(string item)
        {
            //构建测试数据
            level3Item = item;
        }
    }
}

3.新建一个ViewModel类MainWindowViewModel,增加一个列表用于绑定,并构建测试数据列表。

复制代码
 1 public class MainWindowViewModel : ViewModelBase
 2     {
 3         private List<Level1> hierarchicalTestList = new List<Level1>();
 4 
 5         public List<Level1> HierarchicalTestList
 6         {
 7             get => hierarchicalTestList;
 8             set
 9             {
10                 hierarchicalTestList = value;
11                 RaiseChange("HierarchicalTestList");
12             }
13         }
14 
15         public MainWindowViewModel()
16         {
17             for (int i = 0; i < 3; i++)
18             {
19                 hierarchicalTestList.Add(new Level1($"层级1项目@{i}"));
20             }
21         }
22     }

设置Context

复制代码
1 public partial class MainWindow : Window
2     {
3         public MainWindow()
4         {
5             InitializeComponent();
6             this.DataContext = new MainWindowViewModel();
7         }
8     }

4.将TreeView的ItemSource绑定到MainWindowViewModel的HierarchicalTestList

复制代码
1  <TreeView ItemsSource="{Binding HierarchicalTestList}">

5.使用HierarchicalDataTemplate重新定义TreeView的ItemTemplate

这里其实就是一级一级的定义,比如第一级,使用ItemSource绑定它的下一级列表,然后用一个Label显示当前层级要显示的数据。依次定义多级即可。

复制代码
<TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Level1ChildList}" DataType="{x:Type local:Level1}">
                    <Label Content="{Binding Level1Item}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Level2ChildList}" DataType="{x:Type local:Level2}">
                            <Label Content="{Binding Level2Item}"/>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <DataTemplate DataType="{x:Type local:Level3}">
                                    <Label Content="{Binding Level3Item}"/>
                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>

6.运行效果

示例代码

说明:

1.正式使用时,应该将List换成ObservableCollection

2.如果绑定的数据为空,不会生成树节点,而不是生成一个空节点。所以这种方式适用于不规则的 数据。

相关推荐
yantuguiguziPGJ4 小时前
WPF 联合 Web 开发调试流程梳理(基于 Microsoft.Web.WebView2)
前端·microsoft·wpf
Aevget4 小时前
DevExpress WPF中文教程:Data Grid - 如何使用虚拟源?(二)
.net·wpf·界面控件·devexpress·ui开发·数据网格
从孑开始6 小时前
ManySpeech.MoonshineAsr 使用指南
人工智能·ai·c#·.net·私有化部署·语音识别·onnx·asr·moonshine
YuanlongWang7 小时前
C# 中,依赖注入(DI)的实现方式
c#
SmartSoftHelp开发辅助优化8 小时前
C# WinForm 编程高手:程序,进程,线程。程序,窗体,UI,后台。是如何协调工作的?深度解析>SmartSoftHelp魔法精灵工作室
microsoft·ui·c#
大美B端工场-B端系统美颜师9 小时前
工控软件开发选择难?Electron、Qt、WPF 对比
qt·electron·wpf
future_studio10 小时前
聊聊 Unity(小白专享、C# 小程序 之 加密存储)
开发语言·小程序·c#
c#上位机11 小时前
MefBootstrapper在Prism引导程序中的使用
c#·wpf·prism
玩泥巴的14 小时前
.NET驾驭Word之力:基于规则自动生成及排版Word文档
c#·word·.net·com互操作
SunnyDays101114 小时前
C# 实现高保真 Excel 转 PDF(无需 Office 环境)
经验分享·c#·excel转pdf