WPF实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件。其效果如下图:

这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成。它的操作逻辑:
- 当选中“全选”时,列表中所有的项目都会被选中;反之,取消选中“全选”时,所有项都会被取消勾选。
- 在列表中选中部分数据项目时,“全选”框会呈现不确定状态(Indetermine)。
由此看出,“全选”复选框与列表项中的复选框达到了双向控制的效果。
其设计思路:首先,创建自定义控件(CheckListView),在其 ControlTemplate 中定义 CheckBox 和 ListView,并为 ListView 设置 ItemTemplate,在其中增加 CheckBox 控件,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<ControlTemplate TargetType="{x:Type control:CheckListView}"> <Grid Background="{TemplateBinding Background}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <CheckBox Content="全选" /> <ListView x:Name="list" Grid.Row="1"> <ListView.ItemTemplate> <DataTemplate> <CheckBox /> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </ControlTemplate> |
其次,为控件添加两个依赖属性,其中一个为 ItemsSource,即该控件所要接收的数据源,也即选择列表;本质上,这个数据源会指定给其内的 ListView。另外也需要一个属性 IsSelectAllChecked 表示是否选中全选复选框。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public static readonly DependencyProperty IsSelectAllCheckedProperty = DependencyProperty.Register("IsSelectAllChecked", typeof(bool?), typeof(CheckListView), new PropertyMetadata(false)); public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(CheckListView), new PropertyMetadata(null)); /// <summary> /// 返回或设置全选复选框的选中状态 /// </summary> public bool? IsSelectAllChecked { get { return (bool?)GetValue(IsSelectAllCheckedProperty); } set { SetValue(IsSelectAllCheckedProperty, value); } } /// <summary> /// 数据源 /// </summary> public object ItemsSource { get { return (object)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } |
需要注意的一点是,作为一个自定义控件,我们必须考虑它的通用性,所以为了保证能设置各式各样的数据源(如用户列表、物品列表或 XX名称列表),在这里定义一个数据接口,只要数据源中的数据项实现该接口,即可达到通用的效果。该接口定义如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public interface ICheckItem { /// <summary> /// 当前项是否选中 /// </summary> bool IsSelected { get; set; } /// <summary> /// 名称 /// </summary> string Name { get; set; } } |
最后,我们把刚才定的属性绑定的控件上,如下:
|
1
2
3
4
5
6
7
8
|
<CheckBox Content="全选" IsChecked="{Binding IsSelectAllChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" /> <ListView x:Name="list" Grid.Row="1" ItemsSource="{TemplateBinding ItemsSource}"> <ListView.ItemTemplate> <DataTemplate> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" /> </DataTemplate> </ListView.ItemTemplate></ListView> |
接下来,实现具体操作:
首先,通过“全选”复选框来控制所有列表项:这里通过其 Click 事件来执行 CheckAllItems 方法, 在此方法中,会对数据源进行遍历,将其 IsSelected 属性设置为 True 或 False。代码如下:
|
1
2
3
4
5
6
7
|
<CheckBox Content="全选" IsChecked="{Binding IsSelectAllChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction MethodName="CheckAllItems" TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" /> </i:EventTrigger> </i:Interaction.Triggers> </CheckBox> |
|
1
2
3
4
5
6
7
8
9
10
|
/// <summary>/// 全选或清空所用选择/// </summary> public void CheckAllItems() { foreach (ICheckItem item in ItemsSource as IList<ICheckItem>) { item.IsSelected = IsSelectAllChecked.HasValue ? IsSelectAllChecked.Value : false; } } |
然后,通过选中或取消选中列表项时,更新“全选”复选框的状态:在 DataTemplate 中,我们也为 CheckBox 的 Click 事件设置了要触发的方法 UpdateSelectAllState,代码如下:
|
1
2
3
4
5
6
7
8
9
|
<DataTemplate> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction MethodName="UpdateSelectAllState" TargetObject="{Binding RelativeSource={RelativeSource AncestorType=control:CheckListView}}" /> </i:EventTrigger> </i:Interaction.Triggers> </CheckBox></DataTemplate> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/// <summary>/// 根据当前选择的个数来更新全选框的状态/// </summary> public void UpdateSelectAllState() { var items = ItemsSource as IList<ICheckItem>; if (items == null) { return; } // 获取列表项中 IsSelected 值为 True 的个数,并通过该值来确定 IsSelectAllChecked 的值 int count = items.Where(item => item.IsSelected).Count(); if (count == items.Count) { IsSelectAllChecked = true; } else if (count == 0) { IsSelectAllChecked = false; } else { IsSelectAllChecked = null; } } |
这里也有两点需要提醒:
我一开始定义属性 IsSelectAllChecked 时,它的类型是 bool 类型,那么,由于 CheckBox 控件的 IsChecked 值为 null 时,它将呈现 Indetermine 状态,所以后来把它改为 bool? 类型。
在XAML 代码中可以看出,对事件以及事件的响应使用了行为,所以,需要添加引用 System.Windows.Interactivity.dll 和 Microsoft.Expression.Interactions.dll 两个库,并在XMAL 头部添加如下命名空间的引用:
这样,这个控件就基本完成了,接下来是如何使用它。
首先,定义将要在列表中展示的数据项,并为它实现之前提到的 ICheckItem 接口,这里定义了一个 User 类,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class User : BindableBase, ICheckItem { private bool isSelected; private string name; public bool IsSelected { get { return isSelected; } set { SetProperty(ref isSelected, value); } } public string Name { get { return name; } set { SetProperty(ref name, value); } } } |
接下来在 ViewModel 中定义一个列表 List<ICheckItem>,并添加数据,最后在 UI 上为其绑定 ItemsSource 属性即可,在此不再贴代码了,具体请参考源代码。
The TargetObject is the object which has the method to be invoked, if you have the method in your window code-behind then the object is the window itself
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
...etcetera...
x:Name="UserControl">
So your CallMethodAction would be:
<ei:CallMethodAction MethodName="MyMethod"
TargetObject="{Binding ElementName=UserControl, Mode=OneWay}"/>
WPF实现带全选复选框的列表控件的更多相关文章
- WPF: 实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中“全选”时,列表中所有的项目都 ...
- QTableWidget自定义表头QHeaderView加全选复选框
1 QTableWidget自定义表头QHeaderView加全选复选框 在使用QTableWidget时需要在表头添加全选复选框,但是默认的表头无法添加复选框,只能用图片画上去一个复 ...
- ExtJS中,将Grid表头中的全选复选框取消复选
今天发现公司产品用的EXTJS中使用Grid时,Grid表头中的全选复选框的选中状态不是很准确,就写了这个小扩展 在js中加入下面方法,在需要取消全选的地方调用即可,例:Ext.getCmp('gri ...
- [原创]纯JS实现网页中多选复选框checkbox和单选radio的美化效果
图片素材: 最终效果图: <html><title> 纯JS实现网页中多选复选框checkbox和单选radio的美化效果</title><head>& ...
- java freemarker导出word时添加或勾选复选框
最近项目导出word碰到一个需求,要求根据数据动态的决定word里的复选框是否勾选, 公司导出word用的是freemarker,相比较其他技术,freemarker可以很容易的控制输出样式, 在wo ...
- JS-001-单选复选按钮操作
此文主要针对 web 页面中常见元素(例如:单选按钮.复选按钮)的 JavaScript 操作,进行简单的源码示例演示,敬请小主们参阅.若有不足之处,敬请大神指正,不胜感激! 话不多言了,直接上码: ...
- iOS开发-UITableView单选多选/复选实现1
TableView怎样实现单选或者多选呢? 我们的直接思路是改动某一个Cell的样式就可以, 那么改动样式须要通过改动相应的数据, 从这里能够判断我们须要给Cell相应的数据设置一个标志位, 当选中的 ...
- Asp.net绑定带层次下拉框(select控件)
1.效果图 2.数据库中表数据结构 3.前台页面 <select id="pid" runat="server" style="width:16 ...
- WPF进阶技巧和实战03-控件(3-文本控件及列表控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
随机推荐
- 网络编程socket-SocketServer-FTP
16章 网络编程?应该是讲网络之间如何编程来进行通信的章节 16.1.1 客户端/服务器架构?客户端请求访问,服务器端监听请求,处理请求,进行相应的模式16.1.2 客户端/服务器编程?服务器端:创建 ...
- poj 3169&hdu3592(差分约束)
Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9687 Accepted: 4647 Descriptio ...
- LeetCode OJ-- Balanced Binary Tree ***
https://oj.leetcode.com/problems/balanced-binary-tree/ 判断一个二叉树,是否为平衡的.如果是平衡的,则它的每个子树的左右子树高度差不大于1. 递归 ...
- Codeforces Gym100971 F.Two Points (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)
这个题直接推公式就可以. 就是解一元二次方程,用高中学的公式,函数开口向上,求最大值为(4ac-b*b)/4a. 这个题推出来一元二次方程,然后将最大值的公式化简一下.公式很好推. 这个题有疑问,in ...
- VS如何反汇编
1. 打开反汇编窗口:调试模式下,按Ctrl+F11.2. 术语: 2.1 ESP(Extended Stack Pointer): 堆栈指针,寄存器存放当前线程的栈顶指针: i.e: move eb ...
- org.apache.commons.io.Charsets
requiredCharsets:由Java平台支持字符集对象标准名称,构造一个sorted map. public void test() { Map<String, Charset> ...
- html特殊字符编码问题导致的细节问题
今天在写前端html时,一个a标签的链接地址,由于链接地址需要给后台传参数,因此带了部分url参数: 在html源码里写的连接地址是: http://域名/bidder/noticesearch?no ...
- asp.net怎样解决高并发问题
队列+多线程+couchbase缓存 ,解决高并发问题. using System; using System.Collections.Generic; using System.Linq; usin ...
- Picasso,Glide,Fresco那个好?
前言:在Android开发中,图片加载OOM一直困扰着很多开发者,在各种不合理的设计之下也容易导致图片加载OOM的问题,目前开源的比较常用的图片加载库也很多,比如老牌的UIL,Volley,AQuer ...
- 【svn】idea上svn 忽略文件不提交
可以自己新建一个更改文件列表,名字叫忽略 这样 你就可以 单纯的 管理剩余的默认文件了 ======================================================== ...