WPF实现带全选复选框的列表控件
发布时间 - 2026-01-11 02:00:37 点击率:次本文将说明如何创建一个带全选复选框的列表控件。其效果如下图:

这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成。它的操作逻辑:
- 当选中“全选”时,列表中所有的项目都会被选中;反之,取消选中“全选”时,所有项都会被取消勾选。
- 在列表中选中部分数据项目时,“全选”框会呈现不确定状态(Indetermine)。
由此看出,“全选”复选框与列表项中的复选框达到了双向控制的效果。
其设计思路:首先,创建自定义控件(CheckListView),在其 ControlTemplate 中定义 CheckBox 和 ListView,并为 ListView 设置 ItemTemplate,在其中增加 CheckBox 控件,如下:
<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 表示是否选中全选复选框。
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名称列表),在这里定义一个数据接口,只要数据源中的数据项实现该接口,即可达到通用的效果。该接口定义如下:
public interface ICheckItem
{
/// <summary>
/// 当前项是否选中
/// </summary>
bool IsSelected { get; set; }
/// <summary>
/// 名称
/// </summary>
string Name { get; set; }
}
最后,我们把刚才定的属性绑定的控件上,如下:
<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。代码如下:
<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>
/// <summary>
/// 全选或清空所用选择
/// </summary>
public void CheckAllItems()
{
foreach (ICheckItem item in ItemsSource as IList<ICheckItem>)
{
item.IsSelected = IsSelectAllChecked.HasValue ? IsSelectAllChecked.Value : false;
}
}
然后,通过选中或取消选中列表项时,更新“全选”复选框的状态:在 DataTemplate 中,我们也为 CheckBox 的 Click 事件设置了要触发的方法 UpdateSelectAllState,代码如下:
<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>
/// <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 头部添加如下命名空间的引用:
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
这样,这个控件就基本完成了,接下来是如何使用它。
首先,定义将要在列表中展示的数据项,并为它实现之前提到的 ICheckItem 接口,这里定义了一个 User 类,如下:
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 属性即可,在此不再贴代码了,具体请参考源代码。
源码下载
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# WPF
# 复选框
# CheckBox
# 列表控件
# WPF自定义控件和样式之自定义按钮(Button)
# WPF如何自定义TabControl控件样式示例详解
# 超炫酷的WPF实现Loading控件效果
# WPF的ListView控件自定义布局用法实例
# 在WPF中动态加载XAML中的控件实例代码
# C# 使用WPF 用MediaElement控件实现视频循环播放
# WPF自定义TreeView控件样式实现QQ联系人列表效果
# WPF实现ScrollViewer滚动到指定控件处
# WPF开发技巧之花式控件功能扩展详解
# 全选
# 在此
# 自定义
# 并为
# 绑定
# 值为
# 在这里
# 也有
# 我一
# 是由
# 列表中
# 遍历
# 并在
# 将其
# 把它
# 要在
# 而成
# 达到了
# 会对
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
利用python获取某年中每个月的第一天和最后一天
详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南
公司网站制作价格怎么算,公司办个官网需要多少钱?
Laravel如何使用Service Container和依赖注入?(代码示例)
韩国服务器如何优化跨境访问实现高效连接?
Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录
HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】
如何用虚拟主机快速搭建网站?详细步骤解析
C#如何调用原生C++ COM对象详解
android nfc常用标签读取总结
Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
如何快速搭建个人网站并优化SEO?
Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
Laravel如何发送系统通知?(Notification渠道示例)
如何快速上传建站程序避免常见错误?
如何在建站之星绑定自定义域名?
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册
如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
Claude怎样写约束型提示词_Claude约束提示词写法【教程】
Laravel如何使用查询构建器?(Query Builder高级用法)
个人摄影网站制作流程,摄影爱好者都去什么网站?
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
如何在宝塔面板中创建新站点?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
桂林网站制作公司有哪些,桂林马拉松怎么报名?
详解jQuery中的事件
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
C++时间戳转换成日期时间的步骤和示例代码
BootStrap整体框架之基础布局组件
Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】
如何用景安虚拟主机手机版绑定域名建站?
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
MySQL查询结果复制到新表的方法(更新、插入)
Python进程池调度策略_任务分发说明【指导】
如何用狗爹虚拟主机快速搭建网站?
JavaScript Ajax实现异步通信
如何快速搭建二级域名独立网站?
微信推文制作网站有哪些,怎么做微信推文,急?
Swift中switch语句区间和元组模式匹配
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?

