背景
WPF+Prism,View和ViewModel,通过Binding来实现数据的更新和界面的刷新,我的需求是做一个表格,第一列为CheckBox,同时这一列的header也是CheckBox,勾选了header的CheckBox,可以实现所有行的CheckBox全选的功能
界面如下:
实现方法
xaml代码:
<DataGrid
x:Name="dgRoundRobin"
Grid.Row="2"
Height="300"
Margin="0,5,0,0"
AutoGenerateColumns="False"
BorderBrush="Black"
BorderThickness="1"
CanUserAddRows="{Binding DgRobinCanUserAddRows}"
GridLinesVisibility="All"
ItemsSource="{Binding DgRoundRobinItems}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsChecked}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Command="{Binding DataContext.CbRoundRobinAllCheckCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTextColumn
Width="150"
Binding="{Binding MAC}"
Header="MAC" />
<DataGridTextColumn
Width="100"
Binding="{Binding SendCount}"
Header="发送次数" />
<DataGridTextColumn
Width="100"
Binding="{Binding RcvCount}"
Header="接收次数" />
<DataGridTextColumn
Width="100"
Binding="{Binding SuccessRate}"
Header="成功率" />
<DataGridTextColumn
Width="100"
Binding="{Binding Status}"
Header="状态" />
</DataGrid.Columns>
</DataGrid>
我感觉主要的难点就在xaml中的代码编写,这样的方法是创建了一个DataGridCheckBoxColumn
,然后修改了它的HeaderTemplate
,在其中进行了CheckBox的绑定,<CheckBox Command="{Binding DataContext.CbRoundRobinAllCheckCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
这一行是重点,我们用常规手段直接给header中的CheckBox绑定command是行不通的,因为WPF中没有DataGridCheckBoxColumn
映射它(DataGridCheckBoxColumn
不是控件,它没有父控件)
所以需要我们手动找到DataGrid元素,找到他身上的DataContext来绑定CbRoundRobinAllCheckCommand
。
ViewModel中的代码:
DataGrid的ItemSource绑定的DgRoundRobinItems
,这个的定义如下:
private ObservableCollection<DgRoundRobinDeviceInfo> _dgRoundRobinItems = new ObservableCollection<DgRoundRobinDeviceInfo>();
public ObservableCollection<DgRoundRobinDeviceInfo> DgRoundRobinItems
{
get { return _dgRoundRobinItems; }
set { SetProperty(ref _dgRoundRobinItems, value); }
}
ObservableCollection
实现了INotifyCollectionChanged
和INotifyPropertyChanged
,所以这个集合中的Item有新增
或者删除的话,它会自动的调用UI进行更新,特别方便,以前我总是用List声明一个集合,但是当集合中的元素有新增或删除的时候,都得手动重新刷新下集合才行。
但是我还有个需求,就是想当集合中的Item的某个属性有变化的时候,也可以自动的刷新UI界面,不需要我自己来处理,后来发现还真的可以,只需要将Item的Class继承BindableBase
(这是Prism提供的,Community.Mvvm.Toolkit应该是用的ObservableObject),这样子,就可以实现我的需求,代码如下:
public class DgRoundRobinDeviceInfo : BindableBase
{
private bool _isChecked = false;
public bool IsChecked
{
get { return _isChecked; }
set { SetProperty(ref _isChecked, value); }
}
public string MAC { get; set; }
public int SendCount { get; set; }
public int RcvCount { get; set; }
public string SuccessRate { get; set; }
public string Status { get; set; }
}
可以看到,我在DgRoundRobinDeviceInfo
中的IsChecked
属性上面实现了自动更新。