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.

138 lines
5.1 KiB

  1. using System.Linq;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Controls.Primitives;
  5. using System.Windows.Data;
  6. using System.Windows.Input;
  7. namespace BPA.UIControl
  8. {
  9. /// <summary>
  10. /// DataGrid 详细内容展开列
  11. /// </summary>
  12. public class DataGridDetailToggleButtonColumn : DataGridBoundColumn
  13. {
  14. /// <summary>
  15. /// Initializes a new instance of the <see cref="DataGridDetailToggleButtonColumn"/> class.
  16. /// </summary>
  17. static DataGridDetailToggleButtonColumn()
  18. {
  19. var elementStyle = (Style)Application.Current.FindResource("RubyerDataGridDetailToggleButtonColumn");
  20. DataGridBoundColumn.ElementStyleProperty.OverrideMetadata(typeof(DataGridDetailToggleButtonColumn), new FrameworkPropertyMetadata(elementStyle));
  21. DataGridBoundColumn.EditingElementStyleProperty.OverrideMetadata(typeof(DataGridDetailToggleButtonColumn), new FrameworkPropertyMetadata(elementStyle));
  22. }
  23. /// <inheritdoc/>
  24. protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
  25. {
  26. return GenerateToggleButton(isEditing: false, cell);
  27. }
  28. /// <inheritdoc/>
  29. protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
  30. {
  31. return GenerateToggleButton(isEditing: true, cell);
  32. }
  33. /// <summary>
  34. /// Applies the binding.
  35. /// </summary>
  36. /// <param name="target">The target.</param>
  37. /// <param name="property">The property.</param>
  38. internal void ApplyBinding(DependencyObject target, DependencyProperty property)
  39. {
  40. BindingBase binding = Binding;
  41. if (binding != null)
  42. {
  43. BindingOperations.SetBinding(target, property, binding);
  44. }
  45. else
  46. {
  47. BindingOperations.ClearBinding(target, property);
  48. }
  49. }
  50. /// <summary>
  51. /// Applies the style.
  52. /// </summary>
  53. /// <param name="isEditing">If true, is editing.</param>
  54. /// <param name="defaultToElementStyle">If true, default to element style.</param>
  55. /// <param name="element">The element.</param>
  56. internal void ApplyStyle(bool isEditing, bool defaultToElementStyle, FrameworkElement element)
  57. {
  58. Style style = PickStyle(isEditing, defaultToElementStyle);
  59. if (style != null)
  60. {
  61. element.Style = style;
  62. }
  63. }
  64. /// <summary>
  65. /// Picks the style.
  66. /// </summary>
  67. /// <param name="isEditing">If true, is editing.</param>
  68. /// <param name="defaultToElementStyle">If true, default to element style.</param>
  69. /// <returns>A Style.</returns>
  70. private Style PickStyle(bool isEditing, bool defaultToElementStyle)
  71. {
  72. Style style = (isEditing ? EditingElementStyle : ElementStyle);
  73. if (isEditing && defaultToElementStyle && style == null)
  74. {
  75. style = ElementStyle;
  76. }
  77. return style;
  78. }
  79. /// <summary>
  80. /// Generates the toggle button.
  81. /// </summary>
  82. /// <param name="isEditing">If true, is editing.</param>
  83. /// <param name="cell">The cell.</param>
  84. /// <returns>A ToggleButton.</returns>
  85. private ToggleButton GenerateToggleButton(bool isEditing, DataGridCell cell)
  86. {
  87. ToggleButton toggleButton = (cell != null) ? (cell.Content as ToggleButton) : null;
  88. toggleButton ??= new ToggleButton();
  89. toggleButton.IsThreeState = false;
  90. ApplyStyle(isEditing, defaultToElementStyle: true, toggleButton);
  91. ApplyBinding(toggleButton, ToggleButton.IsCheckedProperty);
  92. return toggleButton;
  93. }
  94. /// <inheritdoc/>
  95. protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
  96. {
  97. if (editingElement is ToggleButton toggleButton)
  98. {
  99. toggleButton.Focus();
  100. bool? isChecked = toggleButton.IsChecked;
  101. if (IsMouseLeftButtonDown(editingEventArgs))
  102. {
  103. toggleButton.IsChecked = !isChecked.GetValueOrDefault();
  104. var dataGridCell = editingElement.GetVisualAncestry().OfType<DataGridCell>().FirstOrDefault();
  105. dataGridCell.IsEditing = false;
  106. }
  107. return isChecked;
  108. }
  109. return false;
  110. }
  111. /// <summary>
  112. /// Are the mouse left button down.
  113. /// </summary>
  114. /// <param name="e">The e.</param>
  115. /// <returns>A bool.</returns>
  116. private static bool IsMouseLeftButtonDown(RoutedEventArgs e)
  117. {
  118. if (e is MouseButtonEventArgs mouseButtonEventArgs && mouseButtonEventArgs.ChangedButton == MouseButton.Left)
  119. {
  120. return mouseButtonEventArgs.ButtonState == MouseButtonState.Pressed;
  121. }
  122. return false;
  123. }
  124. }
  125. }