宿迁加油站闹鬼,滚动条颜色,讷河到哈尔滨火车
本文将说明如何创建一个带全选复选框的列表控件。其效果如下图:
这个控件是由一个复选框(checkbox)与一个 listview 组合而成。它的操作逻辑:
由此看出,“全选”复选框与列表项中的复选框达到了双向控制的效果。
其设计思路:首先,创建自定义控件(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 属性即可,在此不再贴代码了,具体请参考源代码。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Net Core Web Api项目与在NginX下发布的方法
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
IdentityServer4实现.Net Core API接口权限认证(快速入门)
ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现
网友评论