WPF之Treeview实现MVVM双向绑定
Treeview分别有两个数据模板HierarchicalDataTemplate(层级数据模板)和DataTemplate(数据模板),分别应用于生成子数据项和普通数据项。
在使用过程中,如果对两个模板的DataType设置为同一类型,运行时会直接报错。

大概原因是添加了俩个相同Key的资源(因为HierarchicalDataTemplate和DataTemplate都是定义在<TreeView.Resources>标签中)。
代码:
public class TypeTreeModel :TypeModel
{
public ObservableCollection<TypeTreeModel> ChildList { get; set; }
= new ObservableCollection<TypeTreeModel>();
}
public class TypeModel
{
public int Id { get; set; }
public string Name { get; set; }
}
<TreeView x:Name="treeView" ItemsSource="{Binding TypeList}" MinWidth="200" MaxHeight="200" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:TypeTreeModel}" ItemsSource="{Binding ChildList}">
<TextBlock Text="{Binding Name}" Margin="3 2"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:TypeModel}">
<TextBlock Text="{Binding Name}" ToolTip="{Binding Id}" Margin="3 2"></TextBlock>
</DataTemplate>
</TreeView.Resources>
</TreeView>
效果图:

TypeList一般都是数据库取出来的数据处理嵌套后的结果。有时候会遇到需求,对于不同的分类有不同的类型。根据双向绑定的规则,我们只需要修改ViewModel中TypeList的内容就可以了。
注意: ObservableCollection只有在列表项发生变化时才会触发页面刷新,即新增或删除时才会反应到页面上。若采用直接赋值的写法,不会触发页面刷新。
推荐更新数据时候的写法:
//清空原先的列表
TypeList.Clear();
list.ForEach(d =>
{
TypeList.Add(d);
});
TreeView.SelectedItem双向绑定
TreeView.SelectedItem是ReadOnly的,所以不能通过简单的绑定方法去获取选中项
最终还是要通过绑定Treeview的SelectedItemChanged事件,来修改ViewModel中的数据
1.直接绑定事件
<TreeView ItemsSource="{Binding TypeList}" SelectedItemChanged="TreeView_OnSelectedItemChanged" />
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
vm.SelectItem = (Cluster)e.NewValue;
}
2.通过Command绑定事件
- 在项目中引用
System.Windows.Interactivity.WPF(简单来说该插件可以将页面控件的Event转为ViewModel中的Command) - 在窗体中添加引用
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
- 绑定
Command到SelectedItemChanged事件
<TreeView x:Name="treeView" ItemsSource="{Binding TypeList}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding SelectItemChangeCommand}"
CommandParameter="{Binding ElementName=treeView,Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
ViewModel:
public class TreeViewModel : ViewModelBase
{
public ObservableCollection<TypeTreeModel> TypeList;
private TypeModel selectItem;
public TypeModel SelectItem
{
get { return selectItem; }
set { this.MutateVerbose(ref selectItem, value, RaisePropertyChanged()); }
}
public TreeViewModel()
{
TypeList = GetData();
}
public ICommand SelectItemChangeCommand
{
get
{
return new CommandBase((param) =>
{
if(param != null)
SelectItem = (TypeModel)param;
});
}
}
}
效果图:

ViewModelBase和CommandBase是自己封装的基类,就是为了写WPF的双向绑定简单点,有兴趣的可以评论向我要。
Demo地址: https://github.com/fxhui/TreeViewDemo
WPF之Treeview实现MVVM双向绑定的更多相关文章
- WPF之AvalonEdit实现MVVM双向绑定
AvalonEdit简介 AvalonEdit是基于WPF开发的代码显示控件,默认支持多种不同语言的关键词高亮,并且可以自定义高亮配置.所以通过AvalonEdit可以快速开发出自己想要的代码编辑器. ...
- 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入
前言:在C/S架构上,WPF无疑已经是"桌面一霸"了.在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用.但是WPF也有很多年的历史了,并且基于MVVM ...
- 【Maui正式版】创建可跨平台的Maui程序,以及有关依赖注入、MVVM双向绑定的实现和演示
前言:Maui终于在昨天(2022年8月9日)推送出来了.今儿就迫不及待来把玩一下先. A.我本地已有VS2022,不过版本比较老,此处选择更新.工具 -> 获取功能和更新里面,可以获取到新版本 ...
- C#使用Xamarin开发可移植移动应用(3.进阶篇MVVM双向绑定和命令绑定)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 嗯..前面 ...
- C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 嗯..前面 ...
- 仿vue实现简易版mvvm双向绑定
项目地址:https://github.com/pangyongsheng/mvvm 1. 指令 vm-bind 单选数据绑定- 将数据显示到标签视图 vm-model : 双向数据绑定 vm-sho ...
- mvvm双向绑定机制的原理和代码实现
mvvm框架的双向绑定,即当对象改变时,自动改变相关的dom元素的值,反之,当dom元素改变时,能自动更新对象的值,当然dom元素一般是指可输出的input元素. 1. 首先实现单向绑定,在指定对象的 ...
- MVVM双向绑定实现之Object.defineProperty
随着web应用的发展,直接操作dom的应用已渐行渐远,取而代之的是时下越来越流行的MVVM框架,dom操作几乎绝迹,这里面自然是框架底层封装的结果.MVVM框架的双向数据绑定使开发效率大大提高:然后在 ...
- 【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
前言: Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了.用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架.依赖属性(Dependen ...
随机推荐
- SQLServer 导入大容量sql文件
cmd命令行,管理员身份运行 执行以下语句:E:\dbbak\abhs\SmartEnglish_data.sql 为文件路径,AbhsEnglish 为要导入的数据库 sqlcmd -i E:\db ...
- 【原创】大叔经验分享(58)kudu写入压力大时报错
kudu写入压力大时报错 19/05/18 16:53:12 INFO AsyncKuduClient: Invalidating location fd52e4f930bc45458a8f29ed1 ...
- VLC播放各种源
RTSP rtsp://admin:Shws1610@192.168.1.33:554/channel/01 UDP 播放推导本机上的udp流 : udp://@:1234 播放其他机器上的ud ...
- 高德地图API-设置考勤范围
<template> <div class="page-setting-setgps"> <!--head--> <div class=& ...
- vue-loading图
父组件给子组件src地址: columns(){ return [ {'title': '图片', 'key': 'img', render(h, {row}){ return h(LoadingIm ...
- webpack 学习过程
什么是WebPack,为什么要使用它? 为什要使用WebPack 现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包.为了简化开发的复杂度,前端社区涌现 ...
- 原型相关的知识点-new的实现原理
let obj = {}let fn = function(){ this.content = 'zhangsan'} let fn2 = new fn() fn2是fn实例化出来的一个对象,要了解n ...
- string字符串长度和字节长度问题
string str = "abcdef 安安安"; int i = str.Length; byte[] bt = System.Text.Encoding.Default.Ge ...
- 记录一则ORA
应用服务器:Windows Server 2008 R2 Enterprise故障现象:项目侧同事反映应用服务器上的程序连接数据库报错:ORA-12560: TNS: 协议适配器错误 1.故障重现 2 ...
- scrapy命令:scrapy genspider详解 转
当我们使用: scrapy startproject taobao 命令创建好scrapy蜘蛛后,你是否注意到,下面还有这么一行内容: F:\scrapyTest> scrapy startpr ...