一、前言
想在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中操作数据来改变前台的层级结构显示。并且逻辑结构与视图结构对应。