WPFUtils.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using System.Windows;
  2. using System.Windows.Controls;
  3. using System.Windows.Media;
  4. using static System.Windows.Forms.VisualStyles.VisualStyleElement;
  5. using Image = System.Windows.Controls.Image;
  6. namespace InABox.WPF
  7. {
  8. public static class WPFUtils
  9. {
  10. public static T? FindLogicalParent<T>(this DependencyObject dependencyObject)
  11. where T : DependencyObject
  12. {
  13. DependencyObject? parent = dependencyObject;
  14. do
  15. {
  16. parent = LogicalTreeHelper.GetParent(parent);
  17. } while(parent != null && parent is not T);
  18. return parent as T;
  19. }
  20. public static int GetRow(this Grid grid, DependencyObject dependencyObject)
  21. {
  22. while (true)
  23. {
  24. var parent = LogicalTreeHelper.GetParent(dependencyObject);
  25. if (parent == null)
  26. return -1;
  27. if (parent == grid)
  28. return Grid.GetRow(dependencyObject as UIElement);
  29. dependencyObject = parent;
  30. }
  31. }
  32. public static int GetRowSpan(this Grid grid, DependencyObject dependencyObject)
  33. {
  34. while (true)
  35. {
  36. var parent = LogicalTreeHelper.GetParent(dependencyObject);
  37. if (parent == null)
  38. return -1;
  39. if (parent == grid)
  40. return Grid.GetRowSpan(dependencyObject as UIElement);
  41. dependencyObject = parent;
  42. }
  43. }
  44. public static void SetGridPosition(this FrameworkElement element, int row, int column, int rowspan, int colspan)
  45. {
  46. element.SetValue(Grid.ColumnProperty, column);
  47. element.SetValue(Grid.ColumnSpanProperty, Math.Max(1, colspan));
  48. element.SetValue(Grid.RowProperty, row);
  49. element.SetValue(Grid.RowSpanProperty, Math.Max(1, rowspan));
  50. }
  51. public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
  52. {
  53. if (depObj != null)
  54. //ContentControl cc = depObj as ContentControl;
  55. //if (cc != null)
  56. //{
  57. // if (cc.Content == null)
  58. // yield return null;
  59. // if (cc.Content is T)
  60. // yield return cc.Content as T;
  61. // foreach (var child in FindVisualChildren<T>(cc.Content as DependencyObject))
  62. // yield return child;
  63. //}
  64. //else
  65. for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
  66. {
  67. var child = VisualTreeHelper.GetChild(depObj, i);
  68. if (child is null)
  69. continue;
  70. if (child is T t)
  71. yield return t;
  72. foreach (var childOfChild in FindVisualChildren<T>(child))
  73. yield return childOfChild;
  74. }
  75. }
  76. private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, bool enabled)
  77. {
  78. var item = new MenuItem { Header = caption, IsEnabled = enabled };
  79. if (image != null)
  80. item.Icon = new Image() { Source = enabled ? image.AsBitmapImage(24, 24) : image.AsGrayScale().AsBitmapImage(24, 24) };
  81. menu.Items.Add(item);
  82. return item;
  83. }
  84. private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, Action? click, bool enabled)
  85. {
  86. var item = DoAddMenuItem(menu, caption, image, enabled);
  87. if (click != null)
  88. {
  89. item.Click += (o, e) =>
  90. {
  91. click();
  92. };
  93. }
  94. return item;
  95. }
  96. private static MenuItem DoAddMenuItem<T>(ItemsControl menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled)
  97. {
  98. var item = DoAddMenuItem(menu, caption, image, enabled);
  99. item.Tag = tag;
  100. item.Click += (o, e) =>
  101. {
  102. click((T)(o as MenuItem)!.Tag);
  103. };
  104. return item;
  105. }
  106. public delegate void CheckToggleAction<T>(T tag, bool isChecked);
  107. private static MenuItem DoAddCheckItem<T>(ItemsControl menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked, bool enabled)
  108. {
  109. var item = new MenuItem { Header = caption, IsEnabled = enabled, IsCheckable = true, IsChecked = isChecked };
  110. item.Tag = tag;
  111. item.Checked += (o, e) =>
  112. {
  113. click((T)(o as MenuItem)!.Tag, true);
  114. };
  115. item.Unchecked += (o, e) =>
  116. {
  117. click((T)(o as MenuItem)!.Tag, false);
  118. };
  119. menu.Items.Add(item);
  120. return item;
  121. }
  122. public static Separator AddSeparator(this ContextMenu menu)
  123. {
  124. var separator = new Separator();
  125. menu.Items.Add(separator);
  126. return separator;
  127. }
  128. public static Separator? AddSeparatorIfNeeded(this ContextMenu menu)
  129. {
  130. if (menu.Items.Count == 0) return null;
  131. var last = menu.Items[menu.Items.Count - 1];
  132. if (last is Separator) return null;
  133. var separator = new Separator();
  134. menu.Items.Add(separator);
  135. return separator;
  136. }
  137. public static MenuItem AddItem(this ContextMenu menu, string caption, Bitmap? image, Action? click, bool enabled = true)
  138. => DoAddMenuItem(menu, caption, image, click, enabled);
  139. public static MenuItem AddItem(this MenuItem menu, string caption, Bitmap? image, Action? click, bool enabled = true)
  140. => DoAddMenuItem(menu, caption, image, click, enabled);
  141. public static MenuItem AddItem<T>(this ContextMenu menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true)
  142. => DoAddMenuItem(menu, caption, image, tag, click, enabled);
  143. public static MenuItem AddItem<T>(this MenuItem menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true)
  144. => DoAddMenuItem(menu, caption, image, tag, click, enabled);
  145. public static MenuItem AddCheckItem<T>(this ContextMenu menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked = false, bool enabled = true)
  146. => DoAddCheckItem<T>(menu, caption, tag, click, isChecked, enabled);
  147. }
  148. }