今天有点时间,做个小例子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> 

源码地址:MyWpfCheckTreeDemo.rar

WPF MVVM实现TreeView的更多相关文章

  1. WPF - MVVM 之TreeView

    在项目中使用OnPropertyChanged方法,最简单的实例: private event PropertyChangedEventHandler PropertyChanged; protect ...

  2. WPF MVVM 验证

    WPF MVVM(Caliburn.Micro) 数据验证 书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model ...

  3. WPF MVVM初体验

    首先MVVM设计模式的结构, Views: 由Window/Page/UserControl等构成,通过DataBinding与ViewModels建立关联: ViewModels:由一组命令,可以绑 ...

  4. WPF/MVVM 快速开始指南(译)(转)

    WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...

  5. WPF如何用TreeView制作好友列表、播放列表

    WPF如何用TreeView制作好友列表.播放列表 前言 TreeView这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表).音乐播放器(播放列表).类库展示器(树形类结构)等都用的是T ...

  6. A WPF/MVVM Countdown Timer

    Introduction This article describes the construction of a countdown timer application written in C# ...

  7. 使用Prism提供的类实现WPF MVVM点餐Demo

    使用Prism提供的类实现WPF MVVM点餐Demo 由于公司开发的技术需求,近期在学习MVVM模式开发WPF应用程序.进过一段时间的学习,感受到:学习MVVM模式,最好的方法就是用MVVM做几个D ...

  8. WPF MVVM使用prism4.1搭建

    WPF MVVM使用prism4.1搭建 MVVM即Model-View-ViewModel,MVVM模式与MVP(Model-View-Presenter)模式相似,主要目的是分离视图(View)和 ...

  9. ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet

    Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家. Stylet是受Caliburn Micro项目的启发, 所以借鉴 ...

随机推荐

  1. 叶金荣:MySQL通用优化技巧

    转自:http://mp.weixin.qq.com/s?__biz=MjM5NDE0MjI4MA==&mid=208777870&idx=1&sn=6efddd6283e4d ...

  2. 使用sysbench进行压力测试

    sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试.数据库目前支持MySQL/Oracle/PostgreSQL/Drizzle,它主要包括以下几 ...

  3. 启动rabbitmq web管理后台插件

    安装完rabbitmq server之后,访问http://server_ip:15672/  无法打开网页, 通过netstat -ano |grep 15672 查看此端口号并没有开启 需要启用 ...

  4. hadooop 配置多网卡 提供跨网段服务

    http://hortonworks.com/blog/multihoming-on-hadoop-yarn-clusters/ https://hadoop.apache.org/docs/r2.6 ...

  5. Uva10082 WERTYU -S.B.S.

    A common typing error is to place the hands on the keyboard one row to the right of the correct posi ...

  6. HDU 5105 Math Problem --数学,求导

    官方题解: f(x)=|a∗x3+b∗x2+c∗x+d|, 求最大值.令g(x)=a∗x3+b∗x2+c∗x+d,f(x)的最大值即为g(x)的正最大值,或者是负最小值.a!=0时, g′(x)=3∗ ...

  7. Unity-WIKI 之 AllocationStats(内存分配)

    组件功能 allocationstats是一个简单的辅助工具,用于显示您的应用程序分配多少内存.它采用GC.GetTotalMemory来跟踪内存使用 使用方法 添加 Allocmem.cs 到场景中 ...

  8. 什么是Activity

    Activity 的生命周期是被以下的函数控制的.public class Activity extends ApplicationContext {      protected void onCr ...

  9. Linux搭建python环境

    环境: CentOS 6.4 前言:CentOS 6.4系统自带的有python2.6.6版本 一.下载文件 python官网:https://www.python.org/downloads/ 版本 ...

  10. JMeter学习(十四)JMeter监控Tomcat性能

    使用jmeter的tomcat监视器功能,可以通过向tomcat的status页面发送get请求,得到资源使用信息,然后转换为只直观的图像方式,这样的话,就可以监视到服务器的资源使用情况,不过需要注意 ...