在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

WPF 带CheckBox、图标的TreeView(转)的更多相关文章

  1. c# WPF——创建带有图标的TreeView

    1.使用数据模板对TreeViewItem进行更改 2.xaml中重写TreeviewItem的控件模板 3.继承TreeViewItem(TreeView中的元素),后台进行控件重写.(介绍此方法) ...

  2. WPF 带CheckBox、图标的TreeView

    WPF 带CheckBox.图标的TreeView 在WPF实际项目开发的时候,经常会用到带CheckBox的TreeView,虽然微软在WPF的TreeView中没有提供该功能,但是微软在WPF中提 ...

  3. iOS使用带字体图标的UIButton(支持各种方向)

    简书地址:http://www.jianshu.com/p/1c288440754d demo地址:https://github.com/Brances/ZMProject

  4. wpf企业应用之带选项框的TreeView

    wpf里面实现层次绑定主要使用HierarchicalDataTemplate,这里主要谈一谈带checkbox的treeview,具体效果见 wpf企业级开发中的几种常见业务场景. 先来看一下我的控 ...

  5. 潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据

    原文:潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据 目前自己对treeview的感慨很多 今天先讲 面对这种 表结构的数据 的其中 ...

  6. Android实现带图标的ListView

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/bear_huangzhen/article/details/23991119 Android实现带图 ...

  7. Silverlight TreeView 带 checkbox和图片

    前段时间做Silverlight TreeView 控件,但是要带checkbox和图片,在网上到处找相关的例子,效果图如下 xaml代码 <UserControl x:Class=" ...

  8. Qt 怎样生成带图标的exe

    一.问题描述 当我们在 Windows 下用 VS 生成 exe 程序时,如果窗口程序指定了图标,那么生成的 exe 程序便是指定的图标模样. 但是,当使用 Qt Creator 编译程序却不同.即使 ...

  9. WPF中Expander控件样式,ListBox的样式(带checkbox)恢复

    Expander控件样式: <ControlTemplate x:Key="ExpanderToggleButton" TargetType="ToggleButt ...

随机推荐

  1. codeforces 559a//Gerald's Hexagon// Codeforces Round #313(Div. 1)

    题意:面积是sqrt(3)/4的多少倍? 做延长线 #pragma comment(linker,"/STACK:1024000000,1024000000") #include& ...

  2. jquery自动填充输入框

    1,这是一个比较简单的页面,你可以复制下来就可以使用.<!doctype html><html lang="en"><head> <met ...

  3. Django rest framework(2)----权限

    一 添加权限 (1)API/utils文件夹下新建premission.py文件,代码如下: message是当没有权限时,提示的信息 #!/usr/bin/env python # coding:u ...

  4. 信号处理函数的返回sigsetjmp/siglongjmp

    由于在信号处理期间自动屏蔽了正在被处理的信号,而使用setjmp/longjmp跳出信号处理程序时又不会自动将 信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽. 可以使用sigsetjmp/s ...

  5. PHP:第一章——按位运算和求余运算(判断奇偶数)

    <?php //按位运算:与1按位运算等于0,输出偶数.如果等于1,输出奇数 //输出偶数: for($i=0;$i<10;$i++){ if(($i & 1)==0){ echo ...

  6. 小L的区间求和

    题目描述 在给定的一个整数序列中,小L希望找到一个连续的区间,这个区间的和能够被k整除,请你帮小L算一下满足条件的最长的区间长度是多少. 输入 第一行输入两个整数n.k.(1 <= n < ...

  7. 告别.NET生成报表统计图的烦恼

    告别.NET生成报表统计图的烦恼 标签: 报表.netstatistics图形数据库文档 2009-10-09 12:00 635人阅读 评论(0) 收藏 举报  分类: .net程序设计(C#)(2 ...

  8. oracle查询在当前数据库下当前用户拥有的表语句

    1.查询表的数目: select count(*) from tabs select count(*) from user_tables 2.查询用户拥有哪些表: select * from tabs ...

  9. vue + element-ui Table的数据多选,多页选择数据回显,分页记录保存选中的数据。

    业务的需要:我要对与会人员勾选,记录所选的与会人员,并且点击到别的页面上时也要记录所勾选的.第一次尝试,每次点击下一页数据都会清空.然后我就去element ui官网查看了api.实现如下: 在tab ...

  10. 玩转X-CTR100 l STM32F4 l DHT11温湿度传感器

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] DHT11数字温湿度传感器是一款含有已校准数字信号输 ...