💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
项目中用到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> ~~~ ~~~ <DataGridCheckBoxColumn ~~~ ~~~ x:Name="_dtcSelected" Header="" HeaderStyle="{StaticResource DataGridCheckboxColumnHeaderStyle1}" CellStyle="{StaticResource DataGridCheckboxCellStyle1}" MinWidth="60" CanUserReorder="False" MaxWidth="60"/> ~~~