WPF 带CheckBox、图标的TreeView

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win32框架,GDI图形编程写一个HelloWorld游戏_c语言

1.如图&#xff0c;实现功能: Hello World!字符串跟随鼠标移动鼠标左击Hello World!颜色为红色鼠标右击Hello World!颜色为蓝色鼠标滚轮滚动改变Hello World!颜色的RGB中的G值 2.实现工具: vs20133.实现步骤: 新建一个win32项目 如图,看到HelloWorldGame.cpp中 _tWinMain()的函…

全景图像拼接——图像融合

图像融合技术就是将配准过后的图像融合成一幅宽视角、大场景的图像。但由于图像采集过程中各种因素的影响,例如光照、角度、距离等,从而导致图像间的光照不均匀、颜色上不连续。 经过配准以后,参考图像和输入图像已经在同一个坐标系下,如果只是取某一幅图像的信息或者简单地…

极详细的ECC讲解 -OOB与ECC

http://blog.csdn.net/dongzhichen/article/details/8249228 详细的ECC讲解 -OOB与ECC 在网络编程中 OOB&#xff08;out of band&#xff09;带外数据 在MTD设备中 OOB 如下所示&#xff1a; http://www.cnblogs.com/bcxx_qin/archive/2009/06/11/1501271.html 极详细的ECC…

前端进阶(8) - 前端开发需要了解的工具集合:webpack, eslint, prettier, ...

前端开发需要了解的工具集合&#xff1a;webpack, eslint, prettier, ... 前端开发需要了解的一些工具&#xff0c;这些工具能够帮助你在项目开发中事半功倍。 1. nrm: npm registry 管理器 registry: npm 远程仓库的地址。 由于众所周知的原因&#xff0c;npm 官方仓库在国内特…

CMOS图像传感器——TOF 图像传感器

一、3D成像技术概述 图像传感器一直以来都是人类研究的热点。但随着当代科学技术发展, 人类对于传统的 2D 图像传感器的要求越来高,不仅期望着更高分辨率,更快速度,更大的动态范围,人类加希望能够获得物体深信息,但是 2D 成 像技术现在已经不能满足人类的需求,所以应运…

AndroidStudio创建jinLibs文件夹

在文件中的buildTypes节点下添加 sourceSets.main { jniLibs.srcDir libs } 如图 转载于:https://www.cnblogs.com/kim-liu/p/7479360.html

内嵌Tomcat的Connector对象的静态代码块

在排查问题的过程中发现Connector对象有一个静态代码块&#xff1a; static {replacements.put("acceptCount", "backlog");replacements.put("connectionLinger", "soLinger");replacements.put("connectionTimeout", &quo…

【Python爬虫学习笔记1】网络协议及请求基础

http协议与https协议 HTTP协议(全称为HyperText Transfer Protocol&#xff0c;超文本传输协议)&#xff0c;是发布和接收HTML页面的方法&#xff0c;其服务端口号为80。 HTTPS协议为HTTP协议的加密版本&#xff0c;其在HTTP下加入了SSL层&#xff0c;服务端口号为443。 URL结构…

快速上手SpyGlass——基本流程

SpyGlass&#xff0c;这是一个很强大的RTL验证级工具。它不仅仅能检查sdc的错误&#xff0c;还能做以下各种检查&#xff1a;Low Power, DFT&#xff0c;CDC&#xff08;Cross Domain Check&#xff09;。 一、基本概念 1、方法学相关 Rule: 是SpyGlass 进行RTL分析的最小单…

快速上手SpyGlass——CDC检查

随着技术的发展&#xff0c;数字电路的集成度越来越高&#xff0c;设计也越来越复杂。很少有系统会只工作在同一个时钟频率。一个系统中往往会存在多个时钟&#xff0c;这些时钟之间有可能是同步的&#xff0c;也有可能是异步的。如果一个系统中&#xff0c;异步时钟之间存在信…

数字后端——低功耗单元库

在之前的文章中&#xff0c;介绍了低功耗设计物理实施的方案&#xff1a; 数字后端——低功耗设计物理实施_沧海一升的博客-CSDN博客_低功耗设计低功耗设计方案所涉及到的物理实施相关内容https://blog.csdn.net/qq_21842097/article/details/119918312 为了实现例如门…

NandFlash详述

1. 硬件特性&#xff1a; 【Flash的硬件实现机制】 Flash全名叫做Flash Memory&#xff0c;属于非易失性存储设备(Non-volatile Memory Device)&#xff0c;与此相对应的是易失性存储设备(Volatile Memory Device)。这类设备&#xff0c;除了Flash&#xff0c;还有其他比较常见…

史上最全的MySQL高性能优化实战总结!

1.1 前言 MySQL对于很多Linux从业者而言&#xff0c;是一个非常棘手的问题&#xff0c;多数情况都是因为对数据库出现问题的情况和处理思路不清晰。在进行MySQL的优化之前必须要了解的就是MySQL的查询过程&#xff0c;很多的查询优化工作实际上就是遵循一些原则让MySQL的优化器…

低功耗设计——基于UPF进行设计

UPF&#xff0c; 统一电源格式UPF(Unified Power Format)是新思(Synopsys)公司通用的电源格式&#xff0c;是一组标准的类Tcl 语言的集合&#xff0c;用来描述芯片设计中的低功耗意图&#xff08;Low-Power Design Intent&#xff09;。 使用UPF 的语言&#xff0c;可以描述供电…

用公众号获取 任意公众号文章列表 软件还是免费

用公众号获取 任意公众号文章列表 软件还是免费还不快点下载 下载 地址 https://pan.baidu.com/s/1jI44Wjs转载于:https://www.cnblogs.com/wx85437898/p/7488590.html

CentOS7时间设置问题

本地安装一个VMWare player虚拟机客户端&#xff0c;并安装了Linux CentOS7 Basic Web Server系统&#xff0c;时区在安装时已经选择了Asia/Shanghai,但是安装完成后&#xff0c;时间和当前外部的时间不一致&#xff0c;如下图 图一 图二 图三 后经搜索发现&#xff0c;由于未开…

低功耗设计——功耗估算

根据在功耗分析的过程中是否有输入向量的提供&#xff0c;功耗估算方法可以分为仿真的方法&#xff08;Simulative&#xff09;和非仿真的方法&#xff08;Non-simulative&#xff09;&#xff1a; 仿真的方法是根据用户所提供的大量输入向量来对电路进行模拟&#xff0c;利用…

Deep Learning(深度学习)学习笔记整理系列三

Deep Learning&#xff08;深度学习&#xff09;学习笔记整理系列 声明&#xff1a; 1&#xff09;该Deep Learning的学习系列是整理自网上很大牛和机器学习专家所无私奉献的资料的。具体引用的资料请看参考文献。具体的版本声明也参考原文献。 2&#xff09;本文仅供学术交流&…

Conformal ECO 流程介绍

之前听说过一句话&#xff0c;没有修过ECO的人生是不完整的。最近就给我整得再次完整了。。。。。。 最近赶项目&#xff0c;RTL freeze之后&#xff0c;后仿发现出了bug&#xff08;还好拦下来了&#xff0c;不然头更大&#xff09;&#xff0c;于是做了一次function ECO&…

Zabbix discoverer processes more than 75% busy

原文发表于cu&#xff1a;2016-06-22 Zabbix discoverer processes more than 75% busy原因及处理。 一&#xff0e;现象 配置了discovery任务后&#xff0c;zabbix dashboard 告警如下&#xff1a; Zabbix discoverer processes more than 75% busy 二&#xff0e;原因 1. 配置…