You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
6.4 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Controls.Primitives;
  10. using System.Windows.Data;
  11. using System.Windows.Media;
  12. namespace BPA.UIControl
  13. {
  14. /// <summary>
  15. /// DataGrid 选择列
  16. /// </summary>
  17. public class DataGridSelectCheckBoxColumn : DataGridCheckBoxColumn
  18. {
  19. /// <summary>
  20. /// Initializes a new instance of the <see cref="DataGridSelectCheckBoxColumn"/> class.
  21. /// </summary>
  22. static DataGridSelectCheckBoxColumn()
  23. {
  24. }
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="DataGridSelectCheckBoxColumn"/> class.
  27. /// </summary>
  28. public DataGridSelectCheckBoxColumn()
  29. {
  30. var headStyle = (Style)Application.Current.FindResource("DataGridSelectCheckBoxColumnHeader");
  31. HeaderStyle = headStyle;
  32. CanUserSort = false;
  33. }
  34. /// <inheritdoc/>
  35. protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
  36. {
  37. return GenerateCheckBox(false, cell);
  38. }
  39. /// <inheritdoc/>
  40. protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
  41. {
  42. return GenerateCheckBox(true, cell);
  43. }
  44. private CheckBox GenerateCheckBox(bool isEditing, DataGridCell cell)
  45. {
  46. CheckBox checkBox = (cell != null) ? (cell.Content as CheckBox) : null;
  47. if (checkBox == null)
  48. {
  49. checkBox = new CheckBox();
  50. if (!isEditing)
  51. {
  52. checkBox.Loaded += CheckBox_Checked;
  53. checkBox.Checked += CheckBox_Checked;
  54. checkBox.Unchecked += CheckBox_Checked;
  55. }
  56. }
  57. checkBox.IsThreeState = IsThreeState;
  58. ApplyStyle(isEditing, defaultToElementStyle: true, checkBox);
  59. ApplyBinding(checkBox, ToggleButton.IsCheckedProperty);
  60. return checkBox;
  61. }
  62. private void CheckBox_Checked(object sender, RoutedEventArgs e)
  63. {
  64. if (sender is CheckBox checkBox)
  65. {
  66. var dataGrid = checkBox.TryGetParentFromVisualTree<DataGrid>();
  67. var columnHeader = GetHeader(this, dataGrid);
  68. var headerCheckBox = columnHeader.TryGetChildFromVisualTree<CheckBox>(x => x is CheckBox);
  69. if (headerCheckBox is null)
  70. {
  71. return;
  72. }
  73. var allValues = new List<bool?>();
  74. foreach (var item in dataGrid.Items)
  75. {
  76. var row = dataGrid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
  77. var cellsPresenter = row.TryGetChildFromVisualTree<DataGridCellsPresenter>(x => x is DataGridCellsPresenter);
  78. if (cellsPresenter is null)
  79. {
  80. continue;
  81. }
  82. var cell = cellsPresenter.ItemContainerGenerator.ContainerFromIndex(DisplayIndex) as DataGridCell;
  83. var currentCheckBox = cell.TryGetChildFromVisualTree<CheckBox>(x => x is CheckBox);
  84. allValues.Add(currentCheckBox.IsChecked);
  85. }
  86. if (allValues.All(x => x == true))
  87. {
  88. headerCheckBox.IsChecked = true;
  89. }
  90. else if (allValues.All(x => x == false))
  91. {
  92. headerCheckBox.IsChecked = false;
  93. }
  94. else
  95. {
  96. headerCheckBox.IsChecked = null;
  97. }
  98. }
  99. }
  100. /// <inheritdoc/>
  101. protected override bool CommitCellEdit(FrameworkElement editingElement)
  102. {
  103. return base.CommitCellEdit(editingElement);
  104. }
  105. private DataGridColumnHeader GetHeader(DataGridColumn column, DependencyObject reference)
  106. {
  107. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
  108. {
  109. DependencyObject child = VisualTreeHelper.GetChild(reference, i);
  110. if ((child is DataGridColumnHeader colHeader) && (colHeader.Column == column))
  111. {
  112. return colHeader;
  113. }
  114. colHeader = GetHeader(column, child);
  115. if (colHeader != null)
  116. {
  117. return colHeader;
  118. }
  119. }
  120. return null;
  121. }
  122. /// <summary>
  123. /// Applies the binding.
  124. /// </summary>
  125. /// <param name="target">The target.</param>
  126. /// <param name="property">The property.</param>
  127. internal void ApplyBinding(DependencyObject target, DependencyProperty property)
  128. {
  129. BindingBase binding = Binding;
  130. if (binding != null)
  131. {
  132. BindingOperations.SetBinding(target, property, binding);
  133. }
  134. else
  135. {
  136. BindingOperations.ClearBinding(target, property);
  137. }
  138. }
  139. /// <summary>
  140. /// Applies the style.
  141. /// </summary>
  142. /// <param name="isEditing">If true, is editing.</param>
  143. /// <param name="defaultToElementStyle">If true, default to element style.</param>
  144. /// <param name="element">The element.</param>
  145. internal void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkElement element)
  146. {
  147. Style style = PickStyle(isEditing, defaultToElementStyle);
  148. if (style != null)
  149. {
  150. element.Style = style;
  151. }
  152. }
  153. /// <summary>
  154. /// Picks the style.
  155. /// </summary>
  156. /// <param name="isEditing">If true, is editing.</param>
  157. /// <param name="defaultToElementStyle">If true, default to element style.</param>
  158. /// <returns>A Style.</returns>
  159. private Style PickStyle(bool isEditing, bool defaultToElementStyle)
  160. {
  161. Style style = (isEditing ? EditingElementStyle : ElementStyle);
  162. if (isEditing && defaultToElementStyle && style == null)
  163. {
  164. style = ElementStyle;
  165. }
  166. return style;
  167. }
  168. }
  169. }