WPF初级——HierarchicalDataTemplate

24 篇文章 21 订阅

一、前言

想在MVVM模式下实现一个侧边栏,最初想做成下图(MaterialDesignThemes风格)的样子,
在这里插入图片描述
这种效果实现起来并不难,ListBox+DataTemplate,然后在ViewModel中绑定一个的集合即可。

但是,项(item)多了之后,它会特别长,而且如果你的项在逻辑关系上存在多层并列关系,用这种线性的ListBox就会与逻辑关系不一致(当然,你可以在ListBox再放几个ListBox,但是WPF中实际上上有更好的控件)。ListBox用来绑定线性集合尚可,线性视图和线性的数据集合是对应的,对于树状的关系,就不太合适了。

那么问题来了,树状的TreeView该绑定怎样的集合呢?
说到底,我就是想后台的数据结构逻辑上和前台视图显示是对应的。
如果不用MVVM的话,那前台直接手动嵌套添加TreeViewItem,做出树形结构的视图就好了。


二、HierarchicalDataTemplate

一番网上冲浪之后,了解到了HierarchicalDataTemplate 类。
正如其名,层级结构——它是能描述层次关系的结构,即有上下级关系。

1. Definition 定义

命名空间:System.Windows
程序集:PresentationFramework.dll
它表示的是支持层级控件的数据模板,如:TreeViewItem或MenuItem。

public class HierarchicalDataTemplate : System.Windows.DataTemplate

2. Example 示例

在VM中定义两个类,Fruit表示一级节点,SubCategory表示二级节点,

    public class Fruit
    {
        // 层次结构中的节点名
        public string Name { get; set; }
        // 子类集合
        public List<SubCategory> SubCategories { get; set; }    
    }
    
    public class SubCategory
    {
        public string Name { get; set; }
    }

XAML中,

	<Grid>
        <Grid.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:Fruit}" ItemsSource="{Binding SubCategories}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:SubCategory}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </Grid.Resources>
        <TreeView ItemsSource="{Binding Fruits}"/>
    </Grid>

核心代码就是Grid.Resources中的部分,它指明了在作用域内的层级结构中,对于不同类型的节点应该以怎样的方式展示。在层级结构的控件元素中,只需要绑定集合,就会以以上方式展开。

当然,VM中还得暴露该集合,并且在XAML的后台cs中添加VM作为上下文,

 	internal class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private ObservableCollection<Fruit> _fruits;
        
        public MainWindowViewModel()
        {
            this.Fruits = new ObservableCollection<Fruit>()
            {
                new Fruit(){ Name = "苹果", SubCategories = new List<SubCategory>{
                    new SubCategory(){ Name = "青苹果🍏"},
                    new SubCategory(){ Name = "红苹果"}
                } }
            };
        }
        
        public ObservableCollection<Fruit> Fruits
        {
            get => _fruits;
            set
            {
                _fruits = value;
                if (_fruits != value)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Fruits)));
                }
            }
        }
    }

效果如下:
在这里插入图片描述

三、结语

通过这种方式,可以以MVVM模式,在VM中操作数据来改变前台的层级结构显示。并且逻辑结构与视图结构对应。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值