• 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"/>
  • 相关阅读:
    'static' can indeed be used in C++ to create a Static Member Function
    关闭QQ2008迷你首页
    开机无法使用欢迎屏幕
    关于U盘”无法复制:磁盘被写保护…”的解决办法
    SQL企业管理器下servers组下无项目解决方法
    COM+应用程序错误8004E00F COM+ 无法与Microsoft 分布
    安装Ms SQL Server 2005 开发版时出现性能计数器要求安装错误的解决办法
    牛人教你这样用Google
    在K3凭证处理中的部份实用操作
    KIS7.5SP2迷你版、标准版在查询数量金额明细账时提示“发生未知错误,系统当前操作被取消,请与金蝶公司的技术支持机构联系”
  • 原文地址:https://www.cnblogs.com/muzizongheng/p/3232648.html
Copyright © 2020-2023  润新知