WPFUtils.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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)
  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. #region Menu Utils
  77. private static void ItemsControlInsert(ItemsControl menu, FrameworkElement item, int index)
  78. {
  79. if (index != -1)
  80. {
  81. menu.Items.Insert(index, item);
  82. }
  83. else
  84. {
  85. menu.Items.Add(item);
  86. }
  87. }
  88. private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, bool enabled, int index = -1)
  89. {
  90. var item = new MenuItem { Header = caption, IsEnabled = enabled };
  91. if (image != null)
  92. item.Icon = new Image() { Source = enabled ? image.AsBitmapImage(24, 24) : image.AsGrayScale().AsBitmapImage(24, 24) };
  93. ItemsControlInsert(menu, item, index);
  94. return item;
  95. }
  96. private static MenuItem DoAddMenuItem(ItemsControl menu, string caption, Bitmap? image, Action? click, bool enabled, int index = -1)
  97. {
  98. var item = DoAddMenuItem(menu, caption, image, enabled, index);
  99. if (click != null)
  100. {
  101. item.Click += (o, e) =>
  102. {
  103. click();
  104. };
  105. }
  106. return item;
  107. }
  108. private static MenuItem DoAddMenuItem<T>(ItemsControl menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled, int index = -1)
  109. {
  110. var item = DoAddMenuItem(menu, caption, image, enabled, index);
  111. item.Tag = tag;
  112. item.Click += (o, e) =>
  113. {
  114. click((T)(o as MenuItem)!.Tag);
  115. };
  116. return item;
  117. }
  118. public delegate void CheckToggleAction<T>(T tag, bool isChecked);
  119. private static MenuItem DoAddCheckItem<T>(ItemsControl menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked, bool enabled, int index = -1)
  120. {
  121. var item = new MenuItem { Header = caption, IsEnabled = enabled, IsCheckable = true, IsChecked = isChecked };
  122. item.Tag = tag;
  123. item.Click += (o, e) =>
  124. {
  125. click((T)(o as MenuItem)!.Tag, item.IsChecked);
  126. };
  127. ItemsControlInsert(menu, item, index);
  128. return item;
  129. }
  130. public static Separator AddSeparator(this ContextMenu menu, int index = -1)
  131. {
  132. var separator = new Separator();
  133. ItemsControlInsert(menu, separator, index);
  134. return separator;
  135. }
  136. public static Separator? AddSeparatorIfNeeded(this ContextMenu menu, int index = -1)
  137. {
  138. if (menu.Items.Count == 0) return null;
  139. var lastIndex = index != -1 ? index - 1 : menu.Items.Count - 1;
  140. if (lastIndex < 0 || lastIndex >= menu.Items.Count) return null;
  141. var last = menu.Items[lastIndex];
  142. if (last is Separator) return null;
  143. var separator = new Separator();
  144. ItemsControlInsert(menu, separator, index);
  145. return separator;
  146. }
  147. public static MenuItem AddItem(this ContextMenu menu, string caption, Bitmap? image, Action? click, bool enabled = true, int index = -1)
  148. => DoAddMenuItem(menu, caption, image, click, enabled, index);
  149. public static MenuItem AddItem(this MenuItem menu, string caption, Bitmap? image, Action? click, bool enabled = true, int index = -1)
  150. => DoAddMenuItem(menu, caption, image, click, enabled, index);
  151. public static MenuItem AddItem<T>(this ContextMenu menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true, int index = -1)
  152. => DoAddMenuItem(menu, caption, image, tag, click, enabled, index);
  153. public static MenuItem AddItem<T>(this MenuItem menu, string caption, Bitmap? image, T tag, Action<T> click, bool enabled = true, int index = -1)
  154. => DoAddMenuItem(menu, caption, image, tag, click, enabled, index);
  155. public static MenuItem AddCheckItem<T>(this ContextMenu menu, string caption, T tag, CheckToggleAction<T> click, bool isChecked = false, bool enabled = true, int index = -1)
  156. => DoAddCheckItem<T>(menu, caption, tag, click, isChecked, enabled, index);
  157. #endregion
  158. }
  159. }