互补共赢 发表于 2023-12-5 18:21:56

WPF DataGrid开箱即用支持全部勾选的DataGridCheckBoxColumn

本文由 飞羽流星(Flithor/毛茸茸松鼠先生/Mr.Squirrel.Downy)原创,欢迎分享转载,但禁止以原创二次发布<br>原文地址:<a href="https://www.cnblogs.com/Flithor/p/17877473.html" target="_blank" rel="noopener">https://www.cnblogs.com/Flithor/p/17877473.html</a>以往在WPF的DataGrid上实现实时勾选交互非常麻烦,要用DataGridTemplateColumn写样式还要写一些后端代码,还有绑定和转换器,或者处理事件。
但是现在都不需要了,使用开箱即用的DataGridCheckAllColumn,简化你的勾选代码实现!
它支持列表筛选变化反馈,支持虚拟化,支持单项勾选变化的更新反馈。
效果预览:

而且非常简单好用:
<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns><strong>注意!</strong>
如果你在DataGrid上设置了<strong>VirtualizingPanel.IsVirtualizing="True"</strong>应用虚拟化
需要同时设置<strong>VirtualizingPanel.VirtualizationMode="Standard"</strong>,避免出现绑定实例错误的BugDataGridCheckAllColumn类的实现:
// 代码作者: 飞羽流星(Flithor/Mr.Squirrel.Downy/毛茸茸松鼠先生)// 开源许可: MIT// =======警告=======// 使用开源代码的风险自负using System;using System.Collections.Generic;using System.ComponentModel;using System.Globalization;using System.Linq;using System.Reflection;using System.Runtime.Remoting.Messaging;using System.Windows;using System.Windows.Controls;using System.Windows.Controls.Primitives;using System.Windows.Data;using System.Windows.Media;using Expression = System.Linq.Expressions.Expression;namespace Flithor_Codes{    ///   /// 一个支持勾选所有的DataGrid列    ///   public class DataGridCheckAllColumn : DataGridBoundColumn    {      #region 私有字段      //列头中的CheckBox      private readonly CheckBox checkAllCheckBox;      //所属DataGrid控件      private DataGrid ownerDatagrid;      //所属DataGrid控件的列表版本,如果版本号改变则说明列表改变      private Func getInnerEnumeratorVersion;      //缓存的列表版本号      private int cachedInnerVersion;      //CheckBox的默认样式      private static Style _defaultElementStyle;      #endregion      #region 初始化控件      public static Style DefaultElementStyle      {            get            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>if (_defaultElementStyle == null)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>{<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    var style = new Style(typeof(CheckBox))<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Setters =<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>            new Setter(UIElement.FocusableProperty, false),<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>            new Setter(CheckBox.HorizontalAlignmentProperty, HorizontalAlignment.Center),<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>            new Setter(CheckBox.VerticalAlignmentProperty, VerticalAlignment.Center)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      }<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    };<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    style.Seal();<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    _defaultElementStyle = style;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>}<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>return _defaultElementStyle;            }      }      static DataGridCheckAllColumn()      {            //重写单元格元素默认样式            ElementStyleProperty.OverrideMetadata(typeof(DataGridCheckAllColumn), new FrameworkPropertyMetadata(DefaultElementStyle));            //使列默认只读            IsReadOnlyProperty.OverrideMetadata(typeof(DataGridCheckAllColumn), new FrameworkPropertyMetadata(true));            //不允许重排此列            CanUserReorderProperty.OverrideMetadata(typeof(DataGridCheckAllColumn), new FrameworkPropertyMetadata(false));            //不允许修改此列宽度            CanUserResizeProperty.OverrideMetadata(typeof(DataGridCheckAllColumn), new FrameworkPropertyMetadata(false));            //不允许点击列头排序项目            CanUserSortProperty.OverrideMetadata(typeof(DataGridCheckAllColumn), new FrameworkPropertyMetadata(false));      }      public DataGridCheckAllColumn()      {            //设置列头            Header = checkAllCheckBox = new CheckBox();      }      protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)      {            if (ownerDatagrid != null) return;            ownerDatagrid = GetParentDataGrid();            if (ownerDatagrid == null) return;            InitInnerVersionDetect(ownerDatagrid.Items);            ((INotifyPropertyChanged)ownerDatagrid.Items).PropertyChanged += OnPropertyChanged;            //如果DataGrid当前已有项目,则初始化绑定            checkAllCheckBox.IsEnabled = ownerDatagrid.Items.Count > 0;            if (checkAllCheckBox.IsEnabled)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>ResetCheckCurrentAllBinding();      }      //寻找所属DataGrid控件(如果还没初始化完毕,可能返回空值)      private DataGrid GetParentDataGrid()      {            DependencyObject elment = checkAllCheckBox;            do            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>elment = VisualTreeHelper.GetParent(elment);            }            while (elment != null && !(elment is DataGrid));            return elment as DataGrid;      }      #endregion      #region 构建单元格元素(方法的功能不言自明)      protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)      {            return GenerateCheckBox(false, cell, dataItem);      }      protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)      {            return GenerateCheckBox(true, cell, dataItem);      }      private CheckBox GenerateCheckBox(bool isEditing, DataGridCell cell, object dataItem)      {            var checkBox = new CheckBox();            ApplyStyle(isEditing, checkBox);            ApplyBinding(dataItem, checkBox);            return checkBox;      }      private void ApplyBinding(object dataItem, CheckBox checkBox)      {            var binding = CloneBinding(Binding, dataItem);            if (binding is Binding newBinding)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>newBinding.Mode = BindingMode.TwoWay;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>newBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;            }            BindingOperations.ClearBinding(checkBox, CheckBox.IsCheckedProperty);            checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);      }      internal void ApplyStyle(bool isEditing, FrameworkElement element)      {            Style style = PickStyle(isEditing);            if (style != null)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>element.Style = style;            }      }      private Style PickStyle(bool isEditing)      {            Style style = isEditing ? EditingElementStyle : ElementStyle;            if (isEditing && (style == null))            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>style = ElementStyle;            }            return style;      }      #endregion      #region 更新绑定      private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)      {            if (ownerDatagrid == null || e.PropertyName != nameof(ownerDatagrid.Items.Count))<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>return;            //如果项目数量发生改变意味着列表更新了            if (ownerDatagrid.Items.Count == 0)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>//如果列表空了,那就移除绑定并禁用列头勾选控件<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>BindingOperations.ClearBinding(checkAllCheckBox, CheckBox.IsCheckedProperty);<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>checkAllCheckBox.IsEnabled = false;            }            else            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>//否则基于当前列表显示项更新绑定<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>ResetCheckCurrentAllBinding();<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>checkAllCheckBox.IsEnabled = true;            }      }      private void ResetCheckCurrentAllBinding()      {            //如果列表版本号改变则更新,否则无需更新            if (ownerDatagrid == null || !InnerVersionChanged()) return;            var checkAllBinding = new MultiBinding            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>Converter = AllBoolStatusConverter.Default,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>Mode = BindingMode.TwoWay            };            //基于所有列表显示项创建绑定            var currentItems = ownerDatagrid.Items.OfType().ToList();            foreach (var item in currentItems)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>checkAllBinding.Bindings.Add(CloneBinding((Binding)Binding, item));            }            //清除旧绑定            BindingOperations.ClearBinding(checkAllCheckBox, CheckBox.IsCheckedProperty);            checkAllCheckBox.SetBinding(CheckBox.IsCheckedProperty, checkAllBinding);      }      //创建获取内部列表版本号的委托      private void InitInnerVersionDetect(ItemCollection itemCollection)      {            //Timestamp属性是内部列表的版本号标识,用于表示列表变更的次数            var collectionTimestampProerty = itemCollection.GetType()<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>.GetProperty("Timestamp", BindingFlags.Instance | BindingFlags.NonPublic);            //使用Linq的Expression来构建访问Timestamp属性的委托方法            getInnerEnumeratorVersion = Expression.Lambda(Expression.Property(<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>Expression.Constant(itemCollection),<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>collectionTimestampProerty)).Compile();      }      //检查内部列表是否发生了更新      private bool InnerVersionChanged()      {            var currentInnerVersion = getInnerEnumeratorVersion.Invoke();            if (currentInnerVersion != cachedInnerVersion)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>cachedInnerVersion = currentInnerVersion;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>return true;            }            return false;      }      //基于已有绑定对象创建一个副本,使用指定的数据源      private static BindingBase CloneBinding(BindingBase bindingBase, object source)      {            switch (bindingBase)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>case Binding binding:<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    var resultBinding = new Binding<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Source = source,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      AsyncState = binding.AsyncState,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      BindingGroupName = binding.BindingGroupName,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      BindsDirectlyToSource = binding.BindsDirectlyToSource,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Converter = binding.Converter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ConverterCulture = binding.ConverterCulture,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ConverterParameter = binding.ConverterParameter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      //ElementName = binding.ElementName,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      FallbackValue = binding.FallbackValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      IsAsync = binding.IsAsync,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Mode = binding.Mode,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnValidationError = binding.NotifyOnValidationError,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Path = binding.Path,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      //RelativeSource = binding.RelativeSource,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      StringFormat = binding.StringFormat,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      TargetNullValue = binding.TargetNullValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      UpdateSourceTrigger = binding.UpdateSourceTrigger,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ValidatesOnDataErrors = binding.ValidatesOnDataErrors,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ValidatesOnExceptions = binding.ValidatesOnExceptions,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      XPath = binding.XPath,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    };<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    foreach (var validationRule in binding.ValidationRules)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      resultBinding.ValidationRules.Add(validationRule);<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    }<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    return resultBinding;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>case MultiBinding multiBinding:<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    var resultMultiBinding = new MultiBinding<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      BindingGroupName = multiBinding.BindingGroupName,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Converter = multiBinding.Converter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ConverterCulture = multiBinding.ConverterCulture,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ConverterParameter = multiBinding.ConverterParameter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      FallbackValue = multiBinding.FallbackValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      Mode = multiBinding.Mode,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnSourceUpdated = multiBinding.NotifyOnSourceUpdated,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnTargetUpdated = multiBinding.NotifyOnTargetUpdated,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      NotifyOnValidationError = multiBinding.NotifyOnValidationError,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      StringFormat = multiBinding.StringFormat,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      TargetNullValue = multiBinding.TargetNullValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      UpdateSourceExceptionFilter = multiBinding.UpdateSourceExceptionFilter,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      UpdateSourceTrigger = multiBinding.UpdateSourceTrigger,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ValidatesOnDataErrors = multiBinding.ValidatesOnDataErrors,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      ValidatesOnExceptions = multiBinding.ValidatesOnDataErrors,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    };<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    foreach (var validationRule in multiBinding.ValidationRules)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      resultMultiBinding.ValidationRules.Add(validationRule);<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    }<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    foreach (var childBinding in multiBinding.Bindings)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      resultMultiBinding.Bindings.Add(CloneBinding(childBinding, source));<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    }<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    return resultMultiBinding;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>case PriorityBinding priorityBinding:<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    var resultPriorityBinding = new PriorityBinding<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      BindingGroupName = priorityBinding.BindingGroupName,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      FallbackValue = priorityBinding.FallbackValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      StringFormat = priorityBinding.StringFormat,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      TargetNullValue = priorityBinding.TargetNullValue,<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    };<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    foreach (var childBinding in priorityBinding.Bindings)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      resultPriorityBinding.Bindings.Add(CloneBinding(childBinding, source));<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    }<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    return resultPriorityBinding;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>default:<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    throw new NotSupportedException("Failed to clone binding");            }      }      ///         /// 用于合并所有bool值到一个值的多值转换器      ///         private class AllBoolStatusConverter : IMultiValueConverter      {            public static readonly AllBoolStatusConverter Default = new AllBoolStatusConverter();            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>if (values.Length == 0 || values.OfType().Count() != values.Length)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    return false;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>// 检查所有项是否和第一项相同<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>var firstStatus = values.First();<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>foreach (var value in values)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>{<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    //如果有不同就返回null,表示第三态<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    if (!Equals(value, firstStatus))<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>      return null;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>}<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>return firstStatus;            }            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)            {<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>//如果汇总的值发生变化则更新所有项目<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>var res = new object;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>for (int i = 0; i < res.Length; i++)<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>    res = value;<DataGrid.Columns>
   
    <fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
   
    <DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>return res;            }      }      #endregion    }}



来源:https://www.cnblogs.com/Flithor/archive/2023/12/05/17877473.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: WPF DataGrid开箱即用支持全部勾选的DataGridCheckBoxColumn