WPF實現(xiàn)帶全選復選框的列表控件
本文將說明如何創(chuàng)建一個帶全選復選框的列表控件。其效果如下圖:

這個控件是由一個復選框(CheckBox)與一個 ListView 組合而成。它的操作邏輯:
- 當選中“全選”時,列表中所有的項目都會被選中;反之,取消選中“全選”時,所有項都會被取消勾選。
- 在列表中選中部分數(shù)據(jù)項目時,“全選”框會呈現(xiàn)不確定狀態(tài)(Indetermine)。
由此看出,“全選”復選框與列表項中的復選框達到了雙向控制的效果。
其設(shè)計思路:首先,創(chuàng)建自定義控件(CheckListView),在其 ControlTemplate 中定義 CheckBox 和 ListView,并為 ListView 設(shè)置 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,即該控件所要接收的數(shù)據(jù)源,也即選擇列表;本質(zhì)上,這個數(shù)據(jù)源會指定給其內(nèi)的 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>
/// 返回或設(shè)置全選復選框的選中狀態(tài)
/// </summary>
public bool? IsSelectAllChecked
{
get { return (bool?)GetValue(IsSelectAllCheckedProperty); }
set { SetValue(IsSelectAllCheckedProperty, value); }
}
/// <summary>
/// 數(shù)據(jù)源
/// </summary>
public object ItemsSource
{
get { return (object)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
需要注意的一點是,作為一個自定義控件,我們必須考慮它的通用性,所以為了保證能設(shè)置各式各樣的數(shù)據(jù)源(如用戶列表、物品列表或 XX名稱列表),在這里定義一個數(shù)據(jù)接口,只要數(shù)據(jù)源中的數(shù)據(jù)項實現(xiàn)該接口,即可達到通用的效果。該接口定義如下:
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>
接下來,實現(xiàn)具體操作:
首先,通過“全選”復選框來控制所有列表項:這里通過其 Click 事件來執(zhí)行 CheckAllItems 方法, 在此方法中,會對數(shù)據(jù)源進行遍歷,將其 IsSelected 屬性設(shè)置為 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;
}
}
然后,通過選中或取消選中列表項時,更新“全選”復選框的狀態(tài):在 DataTemplate 中,我們也為 CheckBox 的 Click 事件設(shè)置了要觸發(fā)的方法 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>
/// 根據(jù)當前選擇的個數(shù)來更新全選框的狀態(tài)
/// </summary>
public void UpdateSelectAllState()
{
var items = ItemsSource as IList<ICheckItem>;
if (items == null)
{
return;
}
// 獲取列表項中 IsSelected 值為 True 的個數(shù),并通過該值來確定 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 時,它將呈現(xiàn) Indetermine 狀態(tài),所以后來把它改為 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"
這樣,這個控件就基本完成了,接下來是如何使用它。
首先,定義將要在列表中展示的數(shù)據(jù)項,并為它實現(xiàn)之前提到的 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>,并添加數(shù)據(jù),最后在 UI 上為其綁定 ItemsSource 屬性即可,在此不再貼代碼了,具體請參考源代碼。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET Mvc開發(fā)之刪除修改數(shù)據(jù)
這篇文章主要介紹了ASP.NET Mvc開發(fā)中的刪除修改數(shù)據(jù)功能,感興趣的小伙伴們可以參考一下2016-03-03
Elasticsearch.Net使用教程 MVC4圖書管理系統(tǒng)(2)
這篇文章主要介紹了Elasticsearch.Net使用教程教會大家利用MVC4制作圖書管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11
.net core2.0下使用Identity改用dapper存儲數(shù)據(jù)(實例講解)
下面小編就為大家分享一篇.net core2.0下使用Identity改用dapper存儲數(shù)據(jù)的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11
DropDownList綁定數(shù)據(jù)表實現(xiàn)兩級聯(lián)動示例
這篇文章主要介紹了DropDownList綁定數(shù)據(jù)表實現(xiàn)兩級聯(lián)動具體實現(xiàn),需要的朋友可以參考下2014-03-03
ASP.NET MVC下Ajax.BeginForm方式無刷新提交表單實例
下面小編就為大家分享一篇ASP.NET MVC下Ajax.BeginForm方式無刷新提交表單實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01
ASP.NET中基于soaphead的webservice安全機制
常會用到WebService來通訊,但WebService發(fā)布后為了能調(diào)用,一般都通過發(fā)布到IIS后調(diào)用 的。在IIS里可以通過匿名訪問,但這樣大家都可能訪問,不安全,下面提供一種基于soaphead的安全機制。2016-05-05

