wpf中为DataGrid添加checkbox支持多选全选

2016-08-20 10:35:34来源:http://muzizongheng.blog.51cto.com/856912/1332958作者:muzizongheng人点击


项目中用到DataGrid, 需要在第一列添加checkbox, 可以多选、全选。其中涉及的概念DataTemplate, DataGridCellStyle, DataGridCellControlTemplate,Binding, OnPropertyChanged等。
有下面是实现思路:
1.继承INotifyPropertyChanged接口,实现OnPropertyChanged方法:public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>/// Raises this object&apos;s PropertyChanged event./// </summary>/// <param name="propertyName">The property that has a new value</param>protected void OnPropertyChanged(string propertyName){PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler){handler(this, new PropertyChangedEventArgs(propertyName));}}
//..................
}
2. 实现viewModel, 添加IsSelected属性, 存储当前多选状态private bool _isSelected = true;
public bool IsSelected{get { return _isSelected; }
set{_isSelected = value;OnPropertyChanged("IsSelected");}}
3.在VM/Model准备好后, 我们接下来开始对DataGrid进行style自定义
4.准备checkbox的DataTemplate:
<DataTemplate x:Key="CheckboxDataTemplate1"> <Grid> <CheckBox x:Name="_chkSelected"Height="16"HorizontalAlignment="Center"VerticalAlignment="Center"Background="{x:Null}"VerticalContentAlignment="Center"HorizontalContentAlignment="Center"Click="_chkSelected_OnClick"IsThreeState="False"IsChecked="{Binding IsSelected, Mode=OneWay, FallbackValue=True}"/> </Grid></DataTemplate>
此示例中checkbox只有简单的2种状态,1)IsChecked属性绑定VM的IsSelected属性;2)Mode为OneWay是因为我们需求是用户可以多选行然后点击某行头选中多行。此功能在Click事件中遍历当前所有选中的行,然后更改其VM的IsSelected属性。因此不需要TwoWay模式;3)在Binding中添加了FallbackValue, 此属性指示当binding失败时给出的默认值。此例中因为DataTemplate也应用在列头, 而列头的DataContext和DataGridRow不同;4)在Click事件处理函数中,判断当前点击的列头还是行头, 更改对应DataContext的IsSelected属性。 如:private void _chkSelected_OnClick(object sender, RoutedEventArgs e){CheckBox chkSelected = e.OriginalSource as CheckBox;if (null == chkSelected){return;}
var studyModel = chkSelected.DataContext as StudyModel;
bool isChecked = chkSelected.IsChecked.HasValue ? chkSelected.IsChecked.Value : true;FrameworkElement templateParent = chkSelected.TemplatedParent is FrameworkElement ? (chkSelected.TemplatedParent as FrameworkElement).TemplatedParent as FrameworkElement : null;
if (templateParent is DataGridColumnHeader){MainViewModel mvm = this.DataContext as MainViewModel;if (null != mvm){foreach (var sm in mvm.StudyList){sm.IsSelected = isChecked;}}}else if (templateParent is DataGridCell){if (null != studyModel && null != this._grdStudyList.SelectedItems && this._grdStudyList.SelectedItems.Contains(studyModel)){foreach (var otherSelected in this._grdStudyList.SelectedItems.OfType<StudyModel>()){otherSelected.IsSelected = isChecked;}}}}
其中MainViewModel为主VM, 其包含一个ObservableCollection<StudyModel>StudyList, 而StudyModel包含IsSelected属性, 二者都实现OnpropertyChanged方法; _grdStudyList为xaml中的DataGrid
5.应用DataTemplate到DataGridColumnHeader和DataGridCell, 如:
<Style x:Key="DataGridCheckboxColumnHeaderStyle1" TargetType="{x:Type DataGridColumnHeader}"><Setter Property="ContentTemplate" Value="{DynamicResource CheckboxDataTemplate1}"/><Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="VerticalAlignment" Value="Stretch"/></Style>
<Style x:Key="DataGridCheckboxCellStyle1" TargetType="{x:Type DataGridCell}"><Setter Property="Padding" Value="20,0"/> <Setter Property="ContentTemplate" Value="{DynamicResource CheckboxDataTemplate1}"/><Setter Property="Background" Value="#FFC1C1C1"/> <Setter Property="BorderBrush" Value="{x:Null}"/><Setter Property="BorderThickness" Value="0"/><Setter Property="Template" Value="{DynamicResource DataGridCheckboxCellControlTemplate1}"/> <Style.Triggers><Trigger Property="IsSelected" Value="True"><Setter Property="Background" Value="#FFC1C1C1"/> <Setter Property="BorderBrush" Value="{x:Null}"/></Trigger></Style.Triggers> </Style>
<ControlTemplate x:Key="DataGridCheckboxCellControlTemplate1" TargetType="{x:Type DataGridCell}"> <Border
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True"><ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></Border></ControlTemplate>
6.应用CellStyle和HeaderStyle到DataGrid:
<DataGrid x:Name="_grdStudyList"ItemsSource="{Binding StudyList}" AutoGenerateColumns="False" FrozenColumnCount="1" Background="#FF999797"><DataGrid.Columns><DataGridCheckBoxColumnx:Name="_dtcSelected" Header=""HeaderStyle="{StaticResource DataGridCheckboxColumnHeaderStyle1}"CellStyle="{StaticResource DataGridCheckboxCellStyle1}" MinWidth="60" CanUserReorder="False" MaxWidth="60"/>

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台