WPF MVVM实现TreeView
今天有点时间,做个小例子WPF MVVM 实现TreeView 只是一个思路大家可以自由扩展
文章最后给出了源码下载地址
图1 图2
模版加上了一个checkbox,选中父类的checkbox 所有的子类也相就选中。
如果子类没有全部父类的checkbox不会选中
用vmmm我们要先实现INotifyPropertyChanged
/// <summary>
///
/// </summary>
public class NotifyPropertyBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
为了避免硬编码错误我写一个扩展方法
/// <summary>
/// 扩展方法
/// 避免硬编码问题
/// </summary>
public static class NotifyPropertyBaseEx
{
public static void SetProperty<T, U>(this T tvm, Expression<Func<T, U>> expre) where T : NotifyPropertyBase, new()
{
string _pro = CommonFun.GetPropertyName(expre);
tvm.OnPropertyChanged(_pro);
}
}
#endregion public class CommonFun
{
/// <summary>
/// 返回属性名
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="U"></typeparam>
/// <param name="expr"></param>
/// <returns></returns>
public static string GetPropertyName<T, U>(Expression<Func<T, U>> expr)
{
string _propertyName = "";
if (expr.Body is MemberExpression)
{
_propertyName = (expr.Body as MemberExpression).Member.Name;
}
else if (expr.Body is UnaryExpression)
{
_propertyName = ((expr.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
return _propertyName;
}
}
下面我们就来实现treeveivew的绑定类
/// <summary>
/// 因为用到泛型了不能写成abstract 类
///
/// </summary>
public class MyTree : NotifyPropertyBase
{ #region 父
public MyTree Parent
{
get;
set;
}
#endregion #region 子
public List<MyTree> Children
{
get;
set;
}
#endregion #region 节点的名字
public string Name
{
get;
set;
}
#endregion #region Constructors
public MyTree(string name)
{
this.Name=name;
this.Children=new List<MyTree>();
}
public MyTree() { } public
#endregion #region CheckBox是否选中
bool? _isChecked;
public bool? IsChecked
{
get
{
return _isChecked;
}
set
{
SetIsChecked(value, true, true);
}
} private void SetIsChecked(bool? value, bool checkedChildren, bool checkedParent)
{
if (_isChecked == value) return;
_isChecked = value;
//选中和取消子类
if (checkedChildren && value.HasValue && Children != null)
Children.ForEach(ch => ch.SetIsChecked(value, true, false)); //选中和取消父类
if (checkedParent && this.Parent != null)
this.Parent.CheckParentCheckState(); //通知更改 this.SetProperty(x => x.IsChecked);
} /// <summary>
/// 检查父类是否选 中
/// 如果父类的子类中有一个和第一个子类的状态不一样父类ischecked为null
/// </summary>
private void CheckParentCheckState()
{
bool? _currentState = this.IsChecked;
bool? _firstState = null;
for (int i = 0; i < this.Children.Count(); i++)
{
bool? childrenState = this.Children[i].IsChecked;
if (i == 0)
{
_firstState = childrenState;
}
else if (_firstState != childrenState)
{
_firstState = null;
}
}
if (_firstState != null) _currentState = _firstState;
SetIsChecked(_firstState, false, true);
} #endregion #region 选中的行 IsSelected
bool _isSelected;
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
_isSelected = value;
this.SetProperty(x => x.IsChecked);
if (_isSelected)
{
SelectedTreeItem = this;
MessageBox.Show("选中的是" + SelectedTreeItem.Name);
}
else
SelectedTreeItem = null;
}
}
#endregion #region 选中的数据
public MyTree SelectedTreeItem
{
get;
set;
}
#endregion #region 创建树 public void CreateTreeWithChildre( MyTree children,bool? isChecked)
{
this.Children.Add(children); children.Parent = this;
children.IsChecked = isChecked;
}
#endregion
}
我们再下面实现ViewModel
public class TreeViewModel:NotifyPropertyBase
{
public List<MyTree> MyTrees
{
get;
set;
}
public TreeViewModel()
{
MyTrees = new List<MyTree>();
MyTrees.Add(MyCreateTree()); }
/// <summary>
/// 创建树
/// </summary>
/// <returns></returns>
public MyTree MyCreateTree()
{
MyTree _myT = new MyTree("中国");
#region 北京
MyTree _myBJ = new MyTree("北京");
_myT.CreateTreeWithChildre(_myBJ, false);
MyTree _HD = new MyTree("海淀区"); MyTree _CY = new MyTree("朝阳区");
MyTree _FT = new MyTree("丰台区");
MyTree _DC = new MyTree("东城区"); _myBJ.CreateTreeWithChildre(_HD, false);
_HD.CreateTreeWithChildre(new MyTree("某某1"), false);
_HD.CreateTreeWithChildre(new MyTree("某某2"), true);
_myBJ.CreateTreeWithChildre(_CY, false);
_myBJ.CreateTreeWithChildre(_FT, false);
_myBJ.CreateTreeWithChildre(_DC, false); #endregion #region 河北
MyTree _myHB = new MyTree("河北");
_myT.CreateTreeWithChildre(_myHB, false);
MyTree _mySJZ = new MyTree("石家庄");
MyTree _mySD = new MyTree("山东"); MyTree _myTS = new MyTree("唐山"); _myHB.CreateTreeWithChildre(_mySJZ, true);
_myHB.CreateTreeWithChildre(_mySD, false);
_myHB.CreateTreeWithChildre(_myTS, false);
#endregion return _myT;
} }
我们再实现一个TreeView的模版
<Window x:Class="MyWpfCheckTreeDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:MyWpfCheckTreeDemo.AppViewModel"
Title="MainWindow" Height="" Width="" Loaded="LoadedEvent">
<Window.Resources>
<HierarchicalDataTemplate x:Key="MyTreeItemTemplate" DataType="{x:Type VM:MyTree}" ItemsSource="{Binding Path=Children,Mode=OneWay}">
<StackPanel x:Name="My_SP" Orientation="Horizontal" Margin="">
<CheckBox IsChecked="{Binding Path=IsChecked}" >
</CheckBox>
<ContentPresenter Content="{Binding Path=Name,Mode=OneTime}" Margin="2,0"/>
</StackPanel>
</HierarchicalDataTemplate>
<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True" />
<Setter Property="IsSelected" Value="{Binding Path=IsSelected,Mode=TwoWay}"/>
</Style>
</Window.Resources>
<Grid>
<DockPanel> <TreeView x:Name="tv" ItemsSource="{Binding MyTrees}"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
ItemTemplate="{StaticResource MyTreeItemTemplate}"
></TreeView>
</DockPanel> </Grid>
</Window>
WPF MVVM实现TreeView的更多相关文章
- WPF - MVVM 之TreeView
在项目中使用OnPropertyChanged方法,最简单的实例: private event PropertyChangedEventHandler PropertyChanged; protect ...
- WPF MVVM 验证
WPF MVVM(Caliburn.Micro) 数据验证 书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model ...
- WPF MVVM初体验
首先MVVM设计模式的结构, Views: 由Window/Page/UserControl等构成,通过DataBinding与ViewModels建立关联: ViewModels:由一组命令,可以绑 ...
- WPF/MVVM 快速开始指南(译)(转)
WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...
- WPF如何用TreeView制作好友列表、播放列表
WPF如何用TreeView制作好友列表.播放列表 前言 TreeView这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表).音乐播放器(播放列表).类库展示器(树形类结构)等都用的是T ...
- A WPF/MVVM Countdown Timer
Introduction This article describes the construction of a countdown timer application written in C# ...
- 使用Prism提供的类实现WPF MVVM点餐Demo
使用Prism提供的类实现WPF MVVM点餐Demo 由于公司开发的技术需求,近期在学习MVVM模式开发WPF应用程序.进过一段时间的学习,感受到:学习MVVM模式,最好的方法就是用MVVM做几个D ...
- WPF MVVM使用prism4.1搭建
WPF MVVM使用prism4.1搭建 MVVM即Model-View-ViewModel,MVVM模式与MVP(Model-View-Presenter)模式相似,主要目的是分离视图(View)和 ...
- ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet
Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家. Stylet是受Caliburn Micro项目的启发, 所以借鉴 ...
随机推荐
- JVM 运行时数据区域
Java虚拟机管理的内存包括以下几个运行时数据区域: 1.程序计数器: 程序计数器是一块比较小的内存空间,是当前线程执行的字节码行号指示器.Java多线程是通过线程轮流切换来实现的,所以每个线程都有一 ...
- 谷歌开源项目Google Preview Image Extractor(PIEX) (附上完整demo代码)
前天偶然看到谷歌开源项目中有一个近乎无人问津的项目Google Preview Image Extractor(PIEX) . 项目地址: https://github.com/google/piex ...
- linux下安装+配置+卸载jdk
一. 解压安装jdk在shell终端下进入jdk1.7.0_55.bin文件所在目录, 执行命令 ./jdk1.7.0_55.bin 这时会出现一段协议,连继敲回车,当询问是否同意的时候,输入yes, ...
- 边工作边刷题:70天一遍leetcode: day 81-1
Alien Dictionary 要点:topological sort,bfs 只有前后两个word之间构成联系,一个word里的c是没有关系的 只要得到两个word第一个不同char之间的part ...
- disabled和readonly的区别?
在博客园中看到这样一篇文章,关于disabled和readonly的区别,以前还真的没有注意它们的区别,还是有必要知道它们的区别的,所以转载了. 这两个属性有类似之处,但是区别也是巨大的,之所以说类似 ...
- python中for和if else的使用
In []: a = set('abcd') In []: b = set('ef') In []: def match(x,y): ....: for i in x: ....: for j in ...
- 第2章 面向对象的设计原则(SOLID):3_依赖倒置原则(DIP)
3. 依赖倒置原则(Dependence Inversion Principle,DIP) 3.1 定义 (1)要依赖抽象,不要依赖具体的实现类.简单的说就是对抽象(或接口)进行编程,不要依赖实现进行 ...
- 利用Clip制作打洞效果
起因 如上篇博文所说,连线原型需要在中间文字上下各留15像素的空白.设计师完成原型之后,问我有没有办法实现,我说,我能想到两种实现方式.其中一种就是上篇博文所说的OpacityMask.第二种就是使用 ...
- Linux搭建PHP+MySQL+Apache环境
环境: CentOS 6.4 MySQL详细安装可参考:http://www.cnblogs.com/yangxia-test/archive/2012/11/12/2766237.html Apac ...
- 如何查看windows xp系统的位数?
1.右击“我的电脑”->属性,可以看到.2.运行dxdiag,在操作系统一行可以看到.3.运行cmd,输入systeminfo,在系统类型一栏可以看到.--简单4.使用一些检测软件也可以看,像鲁 ...