zoukankan      html  css  js  c++  java
  • wpf中为DataGrid添加checkbox支持多选全选

    项目中用到DataGrid, 需要在第一列添加checkbox, 可以多选、全选。
    其中涉及的概念DataTemplate, DataGridCellStyle, DataGridCellControlTemplate,Binding, OnPropertyChanged等。

    有下面是实现思路:

    1.继承INotifyPropertyChanged接口,实现OnPropertyChanged方法:
     public abstract class ViewModelBase : INotifyPropertyChanged

        {

          public event PropertyChangedEventHandler PropertyChanged;

            /// <summary>
            /// Raises this object'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>                   
                 <DataGridCheckBoxColumn 
                            x:Name="_dtcSelected"
                            Header="" 
                            HeaderStyle="{StaticResource DataGridCheckboxColumnHeaderStyle1}" 
                            CellStyle="{StaticResource DataGridCheckboxCellStyle1}"
                            MinWidth="60" CanUserReorder="False" MaxWidth="60"/>
  • 相关阅读:
    录音 静音检测
    Busybox是什么?
    ubuntu 和VMWare共享数据时故障解决
    使用IStream和GDI+在内存中实现图像格式转换
    .Net 玩自动化测试
    【C#|.NET】跳出一致性Hash算法 打造更高效的分布式缓存
    【C#|.NET】从细节出发(一) 通用接口 aop dto 相关
    【linux+C】神器 vim + 指针相关客串
    【C#|.NET】分布式锁服务
    读书笔记: CLR篇 (让你了解C#.Net的实质) (20111219更新)
  • 原文地址:https://www.cnblogs.com/muzizongheng/p/3232648.html
Copyright © 2011-2022 走看看