WPF 带CheckBox、图标的TreeView

在WPF实际项目开发的时候,经常会用到带CheckBox的TreeView,虽然微软在WPF的TreeView中没有提供该功能,但是微软在WPF中提供强大的ItemTemplate模板功能和自定义样式,那我们可以自己写一个这样的控件供自己使用。

我自己写的这个比较简单。

首先写一个供TreeView使用的数据模型,并且实现INotifyPropertyChanged接口,用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知,当属性改变时,相应的UI表现也改变。主要字段Id,Name,Icon,ToolTip,IsChecked,IsExpanded,Parent,Children

//***************************************************
//
// 文件名(FileName)  : TreeModel.cs
//
// 作者(Author)      : zsm
//
// 创建时间(CreateAt):  2013-03-18 14:23:58
//
// 描述(Description) : 供TreeView实用的数据模型
//
//***************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;namespace Com.FMS.Model
{public class TreeModel : INotifyPropertyChanged{#region 私有变量/// <summary>/// Id值/// </summary>private string _id;/// <summary>/// 显示的名称/// </summary>private string _name;/// <summary>/// 图标路径/// </summary>private string _icon;/// <summary>/// 选中状态/// </summary>private bool _isChecked;/// <summary>/// 折叠状态/// </summary>private bool _isExpanded;/// <summary>/// 子项/// </summary>private IList<TreeModel> _children;/// <summary>/// 父项/// </summary>private TreeModel _parent;#endregion /// <summary>/// 构造/// </summary>public TreeModel(){Children = new List<TreeModel>();_isChecked = false;IsExpanded = false;_icon = "/Images/16_16/folder_go.png";}/// <summary>/// 键值/// </summary>public string Id{get { return _id; }set { _id = value; }}/// <summary>/// 显示的字符/// </summary>public string Name{get { return _name; }set { _name = value; }}/// <summary>/// 图标/// </summary>public string Icon{get { return _icon; }set { _icon = value; }}/// <summary>/// 指针悬停时的显示说明/// </summary>public string ToolTip {get {return String.Format("{0}-{1}", Id, Name);}}/// <summary>/// 是否选中/// </summary>public bool IsChecked{get{return _isChecked;}set{if (value != _isChecked){_isChecked = value;NotifyPropertyChanged("IsChecked");if (_isChecked){//如果选中则父项也应该选中if (Parent != null){Parent.IsChecked = true;}}else{//如果取消选中子项也应该取消选中foreach (TreeModel child in Children){child.IsChecked = false;}}}}}/// <summary>/// 是否展开/// </summary>public bool IsExpanded{get { return _isExpanded; }set{if (value != _isExpanded){//折叠状态改变_isExpanded = value;NotifyPropertyChanged("IsExpanded");}}}/// <summary>/// 父项/// </summary>public TreeModel Parent{get { return _parent; }set { _parent = value; }}/// <summary>/// 子项/// </summary>public IList<TreeModel> Children{get { return _children; }set { _children = value; }}/// <summary>/// 设置所有子项的选中状态/// </summary>/// <param name="isChecked"></param>public void SetChildrenChecked(bool isChecked){foreach (TreeModel child in Children){child.IsChecked = IsChecked;child.SetChildrenChecked(IsChecked);}}/// <summary>/// 设置所有子项展开状态/// </summary>/// <param name="isExpanded"></param>public void SetChildrenExpanded(bool isExpanded) {foreach (TreeModel child in Children){child.IsExpanded = isExpanded;child.SetChildrenExpanded(isExpanded);}}/// <summary>/// 属性改变事件/// </summary>public event PropertyChangedEventHandler PropertyChanged;private void NotifyPropertyChanged(String info){if (PropertyChanged != null){PropertyChanged(this, new PropertyChangedEventArgs(info));}}}
}

创建一个用户控件,主要含有一个TreeView控件,ContextMenu右键菜单项,UI代码如下(其中的路径请根据实际修改):

<UserControl x:Class="Com.FMS.View.UserControls.ZsmTreeView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Com.FMS.Model"mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"><Grid><DockPanel><Border DockPanel.Dock="Bottom"><StackPanel Orientation="Horizontal" ToolTip="右键有更多功能哦!"><Image Height="16" Width="16" Source="Images/16_16/emoticon_smile.png"></Image><Label Content="右键有更多功能哦!" Foreground="Gray"></Label></StackPanel></Border><Border><TreeView Name="tvZsmTree"><TreeView.ContextMenu><ContextMenu><MenuItem Name="menuExpandAll" Header="全部展开" Click="menuExpandAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/folder_open_arrow.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuUnExpandAll" Header="全部折叠" Click="menuUnExpandAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/folder_close_arrow.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuSelectAll" Header="全部选中" Click="menuSelectAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/tick.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuUnSelectAll" Header="全部取消" Click="menuUnSelectAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/delete.png" /></MenuItem.Icon></MenuItem></ContextMenu></TreeView.ContextMenu><TreeView.ItemContainerStyle><Style TargetType="TreeViewItem"><Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"></Setter><EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/></Style></TreeView.ItemContainerStyle><TreeView.ItemTemplate><HierarchicalDataTemplate DataType="{x:Type local:TreeModel}"  ItemsSource="{Binding Children}"><StackPanel  Margin="-2,0,0,0" Orientation="Horizontal" x:Name="staTree"><CheckBox ToolTip="{Binding ToolTip}" FontSize="14" FontFamily="微软雅黑" Tag="{Binding Children}" IsChecked="{Binding IsChecked, Mode=TwoWay}"><StackPanel Orientation="Horizontal"><Image VerticalAlignment="Center" Source="{Binding Icon}" ></Image><TextBlock Text="{Binding Name}"></TextBlock></StackPanel><CheckBox.ContextMenu><ContextMenu><MenuItem Name="menuSelectAllChild" Header="全部选中子项" Click="menuSelectAllChild_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/tick.png" /></MenuItem.Icon></MenuItem></ContextMenu></CheckBox.ContextMenu></CheckBox></StackPanel><HierarchicalDataTemplate.Triggers><DataTrigger Binding="{Binding IsChecked}" Value="true"><Setter TargetName="staTree" Property="Background" Value="White"/></DataTrigger></HierarchicalDataTemplate.Triggers></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView></Border></DockPanel></Grid>
</UserControl>

交互逻辑的代码中,现在主要有控件数据ItemsSourceData属性,设置对应Id的项为选中状态SetCheckedById、忽略层次关系的情况下获取选中项CheckedItemsIgnoreRelation等方法,以及右键的选中所有子项菜单、全部选中、全部取消选中、全部折叠、全部展开等事件,交互逻辑代码为:

//***************************************************
//
// 文件名(FileName)  : ZsmTreeView.xaml.cs
//
// 作者(Author)      : zsm
//
// 创建时间(CreateAt):  2013-03-15 16:52:40
//
// 描述(Description) : 带CheckBox的TreeView控件的交互逻辑代码
//
//***************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace Com.FMS.View.UserControls
{/// <summary>/// ZsmTreeView.xaml 的交互逻辑/// </summary>public partial class ZsmTreeView : UserControl{#region 私有变量属性/// <summary>/// 控件数据/// </summary>private IList<Model.TreeModel> _itemsSourceData;#endregion/// <summary>/// 构造/// </summary>public ZsmTreeView(){InitializeComponent();}/// <summary>/// 控件数据/// </summary>public IList<Model.TreeModel> ItemsSourceData {get { return _itemsSourceData; }set{_itemsSourceData = value;tvZsmTree.ItemsSource = _itemsSourceData;}}/// <summary>/// 设置对应Id的项为选中状态/// </summary>/// <param name="id"></param>/// <returns></returns>public int SetCheckedById(string id, IList<Model.TreeModel> treeList) {foreach (var tree in treeList){if (tree.Id.Equals(id)){tree.IsChecked = true;return 1;}if (SetCheckedById(id, tree.Children) == 1){return 1;}}return 0;}/// <summary>/// 设置对应Id的项为选中状态/// </summary>/// <param name="id"></param>/// <returns></returns>public int SetCheckedById(string id){foreach (var tree in ItemsSourceData){if (tree.Id.Equals(id)){tree.IsChecked = true;return 1;}if (SetCheckedById(id, tree.Children) == 1){return 1;}}return 0;}/// <summary>/// 获取选中项/// </summary>/// <returns></returns>public IList<Model.TreeModel> CheckedItemsIgnoreRelation(){return GetCheckedItemsIgnoreRelation(_itemsSourceData);}/// <summary>/// 私有方法,忽略层次关系的情况下,获取选中项/// </summary>/// <param name="list"></param>/// <returns></returns>private IList<Model.TreeModel> GetCheckedItemsIgnoreRelation(IList<Model.TreeModel> list){IList<Model.TreeModel> treeList = new List<Model.TreeModel>();foreach (var tree in list){if (tree.IsChecked){treeList.Add(tree);}foreach (var child in GetCheckedItemsIgnoreRelation(tree.Children)){treeList.Add(child);}}return treeList;}/// <summary>/// 选中所有子项菜单事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuSelectAllChild_Click(object sender, RoutedEventArgs e){if (tvZsmTree.SelectedItem != null){Model.TreeModel tree = (Model.TreeModel)tvZsmTree.SelectedItem;tree.IsChecked = true;tree.SetChildrenChecked(true);}}/// <summary>/// 全部展开菜单事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuExpandAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsExpanded = true;tree.SetChildrenExpanded(true);}}/// <summary>/// 全部折叠菜单事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuUnExpandAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsExpanded = false;tree.SetChildrenExpanded(false);}}/// <summary>/// 全部选中事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuSelectAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsChecked = true;tree.SetChildrenChecked(true);}}/// <summary>/// 全部取消选中/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuUnSelectAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsChecked = false;tree.SetChildrenChecked(false);}}/// <summary>/// 鼠标右键事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e){TreeViewItem item = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;if (item != null){item.Focus();e.Handled = true;}}static DependencyObject VisualUpwardSearch<T>(DependencyObject source){while (source != null && source.GetType() != typeof(T))source = VisualTreeHelper.GetParent(source);return source;}}
}

在使用控件的时候,要在xaml中引入命名控件(根据实际引入)  

xmlns:my="clr-namespace:Com.FMS.View.UserControls"

<!--使用控件--><my:ZsmTreeView x:Name="ztvModule" /> 

为控件赋值:

ztvModule.ItemsSourceData = treeList;//treeList为IList<TreeModel>类型

本文转自 http://www.cnblogs.com/zsmhhfy/archive/2013/03/18/2965755.html

转载于:https://www.cnblogs.com/1175429393wljblog/p/7479144.html

WPF 带CheckBox、图标的TreeView相关推荐

  1. Silverlight Telerik控件学习:带CheckBox复选框的树形TreeView控件

    在web开发中,带checkbox的tree是一个很有用的东东,比如权限选择.分类管理,如果不用sl,单纯用js+css实现是很复杂的,有了SL之后,就变得很轻松了 解决方案一: 利用Silvelri ...

  2. c#.net中创建带图标的ListBox

    下面的代码实现了带图标的ListBoox的功能,可以直接拷贝即可运行.运行结果如下: using System; using System.Drawing; using System.Collecti ...

  3. CSS/HTML 5简洁带图标的input日期选择器

    CSS/HTML 5简洁带图标的input日期选择器 说明 css代码 html代码 演示效果图 说明 演示效果分辨率为1980x1080分辨率效果 高度可定制修改 纯css代码控制 使用的input ...

  4. WPF MVVM模式 带CheckBox的树形图

    前不久做项目中有设计到树形图,还是带CheckBox的树形图,可伤我这种小白的脑筋了,上网找了好多资料参考写出来了,下面来看一下: 首先看这个带CheckBox树形图长啥样,只是一个简单的二级菜单,如 ...

  5. Qt之QSS:带CheckBox的QGroupBox及其样式设计

    前言 在引入QGroupBox的QSS时,会出现下图中的三种问题,导致界面显示极其丑陋.所以要改变QSS设置使界面更bf~ 图a 左边显示问题 图b 标题下沉问题 图c 不对称 下面是两个方式改变QS ...

  6. Cytoscape制作带bar图和pie图节点的网络图

    采用cytoscape制作带bar图和pie图节点的网络图 作者:中科院微生物所 陈亮博士 本教程旨在告诉大家如何使用cytoscape根据Node信息表格制作带有barplot信息节点的网络图.以安 ...

  7. WPF 带水印的密码输入框实现

    WPF 带水印的密码输入框实现 原文:WPF 带水印的密码输入框实现 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/articl ...

  8. C#编写最小化时隐藏为任务栏图标的Window appllication

    C#编写最小化时隐藏为任务栏图标的Window appllication. 1.设置WinForm窗体属性showinTask=false 2.加notifyicon控件notifyIcon1,为控件 ...

  9. 数据结构——图-有向带权图的邻接表

    #include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型(char) #define V ...

最新文章

  1. camera中LENS和SENSOR的CRA是如何搭配的?
  2. nginx+keepalived高可用web架构
  3. 一体机怎么修复音频服务器,教学触摸一体机没有声音怎么办?
  4. 用户路径分析:揭秘你的用户行为偏好习惯
  5. java类声明语句_Java面向对象编程-类的声明周期
  6. ubuntu安装minisat_minisat 安装指南
  7. 深入理解计算机系统(3.3)------操作数指示符和数据传送指令
  8. VS2010与.NET4系列 6.ASP.NET,HTML,JavaScript片断支持
  9. win32 粒子编辑器
  10. SMB协议(445)
  11. jvm学习——jvm内存区域
  12. Office协同办公讲解以及软件归纳
  13. MFC中有关鼠标单击双击响应的问题
  14. CVE-2019-11478 Sack SlownessExcess Resource Usage漏洞解析与利用
  15. Widget-苹果.谷歌和诺基亚着迷的网络新思维
  16. 你 --- 短诗四句
  17. React Native从入门到实战--开发环境搭建
  18. 云服务器是什么?云服务器有什么作用?
  19. YOLOV4垃圾检测召回率提升
  20. Vue 官方成员 Hcy:怎么才能有尤雨溪一半强,该怎么学习?

热门文章

  1. Eigen入门之密集矩阵 9 - 别名混乱Aliasing
  2. pandas内置绘图_使用Pandas内置功能探索数据集
  3. MSP430程序跑飞原因
  4. mysql 8.0数据备份恢复_MySQL 8.0 增强逻辑备份恢复工具介绍-爱可生
  5. LeetCode面试题03. 数组中重复的数字
  6. b树索引 java_B树索引最通俗易懂的介绍
  7. 从服务器上传和下载文件方法
  8. Random Forest 资源汇总(待续)
  9. vue-router的路由
  10. Netty源码分析第5章(ByteBuf)----第5节: directArena分配缓冲区概述