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>类型
显示效果:
其实还可以完成共多功能,等有时间在去写。
WPF 带CheckBox、图标的TreeView的更多相关文章
- c# WPF——创建带有图标的TreeView
1.使用数据模板对TreeViewItem进行更改 2.xaml中重写TreeviewItem的控件模板 3.继承TreeViewItem(TreeView中的元素),后台进行控件重写.(介绍此方法) ...
- WPF 带CheckBox、图标的TreeView(转)
在WPF实际项目开发的时候,经常会用到带CheckBox的TreeView,虽然微软在WPF的TreeView中没有提供该功能,但是微软在WPF中提供强大的ItemTemplate模板功能和自定义样式 ...
- iOS使用带字体图标的UIButton(支持各种方向)
简书地址:http://www.jianshu.com/p/1c288440754d demo地址:https://github.com/Brances/ZMProject
- wpf企业应用之带选项框的TreeView
wpf里面实现层次绑定主要使用HierarchicalDataTemplate,这里主要谈一谈带checkbox的treeview,具体效果见 wpf企业级开发中的几种常见业务场景. 先来看一下我的控 ...
- 潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据
原文:潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据 目前自己对treeview的感慨很多 今天先讲 面对这种 表结构的数据 的其中 ...
- Android实现带图标的ListView
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/bear_huangzhen/article/details/23991119 Android实现带图 ...
- Silverlight TreeView 带 checkbox和图片
前段时间做Silverlight TreeView 控件,但是要带checkbox和图片,在网上到处找相关的例子,效果图如下 xaml代码 <UserControl x:Class=" ...
- Qt 怎样生成带图标的exe
一.问题描述 当我们在 Windows 下用 VS 生成 exe 程序时,如果窗口程序指定了图标,那么生成的 exe 程序便是指定的图标模样. 但是,当使用 Qt Creator 编译程序却不同.即使 ...
- WPF中Expander控件样式,ListBox的样式(带checkbox)恢复
Expander控件样式: <ControlTemplate x:Key="ExpanderToggleButton" TargetType="ToggleButt ...
随机推荐
- MySQL数据库的优化-运维架构师必会高薪技能,笔者近六年来一线城市工作实战经验
原文地址:http://liangweilinux.blog.51cto.com/8340258/1728131 首先在此感谢下我的老师年一线实战经验,我当然不能和我的老师平起平坐,得到老师三分之一的 ...
- t-sql 中between and 的一种写法
t-sql 中between and 的一种写法: where GETDATE() BETWEEN BeginDateTime AND EndDateTime; BeginDateTime,EndDa ...
- puppet任务计划
- Python运行机制
闲来无事,简单画了一下Python的运行机制,纯属娱乐:
- Yii Framework 开发教程Zii组件-Tabs示例
有关Yii Tab类: http://www.yiichina.com/api/CTabView http://www.yiichina.com/api/CJuiTabs http://blog.cs ...
- dp hdu-4433 locker
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4433 题目大意: 给两个长度相等的数字串s1,s2.每次操作可以把连续的最多三位都+1或-1,如果超 ...
- CONTROLS: <> TYPE TABLEVIEW USING SCREEN<>.在 ABAP/4 中声明表格 控制
在 ABAP/4 中声明表格 控制 在屏幕中使 用表格控制 时,必须在 ABAP/4 程序中同时 声明表格控 制结构和表 格控制字段 . 例如: TABLES: SFLIGHT. CONTROLS ...
- 笔记本开了WIFI之后只能上QQ,上不了网页的解决方法
前几天拉了宽带之后,开了WIFI,发现WIFI能上网,但是电脑就上不了网页. 把本地连接的DNS指定一下,(电信)指定为202.102.192.68
- easyui常用控件样式收藏
CSS类定义: div easyui-window window窗口样式 属性如下: 1) modal:是否生成模态窗口.tru ...
- PYTHON queue
http://blog.csdn.net/bravezhe/article/details/8588437