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.

256 lines
9.3 KiB

  1. using BPA.UIControl.Commons;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Automation;
  9. using System.Windows.Controls;
  10. using System.Windows.Controls.Primitives;
  11. using System.Windows.Media;
  12. namespace BPA.UIControl
  13. {
  14. /// <summary>
  15. /// FrameworkElement 扩展
  16. /// </summary>
  17. public static class FrameworkElementExtension
  18. {
  19. /// <summary>
  20. /// 获取 root 元素
  21. /// </summary>
  22. /// <param name="dependencyObject">依赖对象</param>
  23. /// <returns>root 元素</returns>
  24. public static DependencyObject GetRoot(this DependencyObject dependencyObject)
  25. {
  26. DependencyObject result = dependencyObject;
  27. while ((dependencyObject = VisualTreeHelper.GetParent(dependencyObject)) != null)
  28. {
  29. result = dependencyObject;
  30. }
  31. return result;
  32. }
  33. /// <summary>
  34. /// 查找父元素
  35. /// </summary>
  36. /// <typeparam name="T">类型</typeparam>
  37. /// <param name="element">元素</param>
  38. /// <returns>父元素</returns>
  39. public static T FindParent<T>(this FrameworkElement element) where T : FrameworkElement
  40. {
  41. T t = default;
  42. while (element != null)
  43. {
  44. t = element as T;
  45. if (t != null)
  46. {
  47. break;
  48. }
  49. element = element.Parent as FrameworkElement;
  50. }
  51. return t;
  52. }
  53. /// <summary>
  54. /// 获取最顶层父元素
  55. /// </summary>
  56. /// <typeparam name="T">类型</typeparam>
  57. /// <param name="dependencyObject">依赖对象</param>
  58. /// <returns>父元素</returns>
  59. public static T GetOldestParent<T>(this DependencyObject dependencyObject) where T : DependencyObject
  60. {
  61. T t;
  62. while ((t = VisualTreeHelper.GetParent(dependencyObject) as T) != null)
  63. {
  64. dependencyObject = t;
  65. }
  66. return dependencyObject.AssertCast<T>();
  67. }
  68. /// <summary>
  69. /// 尝试查找资源
  70. /// </summary>
  71. /// <typeparam name="T">类型</typeparam>
  72. /// <param name="root">元素</param>
  73. /// <param name="resourceKey">资源 key</param>
  74. /// <returns>资源</returns>
  75. internal static T TryFindResourceUp<T>(this FrameworkElement root, object resourceKey)
  76. {
  77. if (root != null && root.Resources.Contains(resourceKey))
  78. {
  79. object obj = root.Resources[resourceKey];
  80. if (!(obj is T))
  81. {
  82. return default;
  83. }
  84. return (T)obj;
  85. }
  86. else
  87. {
  88. if (root.Parent is FrameworkElement)
  89. {
  90. return ((FrameworkElement)root.Parent).TryFindResourceUp<T>(resourceKey);
  91. }
  92. return default;
  93. }
  94. }
  95. /// <summary>
  96. /// 获取子元素
  97. /// </summary>
  98. /// <typeparam name="T">类型</typeparam>
  99. /// <param name="parent">父元素</param>
  100. /// <returns>子元素</returns>
  101. public static T TryGetChildPartFromVisualTree<T>(this FrameworkElement parent) where T : FrameworkElement
  102. {
  103. return parent.TryGetChildFromVisualTree<T>(null);
  104. }
  105. /// <summary>
  106. /// 根据 Name 获取子元素
  107. /// </summary>
  108. /// <typeparam name="T">类型</typeparam>
  109. /// <param name="parent">父元素</param>
  110. /// <param name="partName">名称</param>
  111. /// <returns>子元素</returns>
  112. public static T TryGetChildPartFromVisualTree<T>(this FrameworkElement parent, string partName) where T : FrameworkElement
  113. {
  114. ValidateArgument.NotNullOrEmpty(partName, "partName");
  115. return parent.TryGetChildFromVisualTree<T>((FrameworkElement childControl) => childControl.Name == partName);
  116. }
  117. /// <summary>
  118. /// 根据 AutomationId 获取子元素
  119. /// </summary>
  120. /// <typeparam name="T">类型</typeparam>
  121. /// <param name="parent">父元素</param>
  122. /// <param name="automationId">自动 ID</param>
  123. /// <returns>子元素</returns>
  124. internal static T TryGetChildWithAutomationIdFromVisualTree<T>(this FrameworkElement parent, string automationId) where T : FrameworkElement
  125. {
  126. ValidateArgument.NotNullOrEmpty(automationId, "automationId");
  127. return parent.TryGetChildFromVisualTree<T>((FrameworkElement childControl) => AutomationProperties.GetAutomationId(childControl) == automationId);
  128. }
  129. /// <summary>
  130. /// VisualTree 获取子元素
  131. /// </summary>
  132. /// <typeparam name="T">类型</typeparam>
  133. /// <param name="parent">父元素</param>
  134. /// <param name="evaluateChild">子元素表达式</param>
  135. /// <returns>子元素</returns>
  136. internal static T TryGetChildFromVisualTree<T>(this FrameworkElement parent, Func<FrameworkElement, bool> evaluateChild) where T : FrameworkElement
  137. {
  138. ValidateArgument.NotNull(parent, "parent");
  139. FrameworkElement frameworkElement = null;
  140. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
  141. {
  142. frameworkElement = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
  143. if (frameworkElement != null && (frameworkElement is T && (evaluateChild == null || evaluateChild.Invoke(frameworkElement)) || (frameworkElement = frameworkElement.TryGetChildFromVisualTree<T>(evaluateChild)) != null))
  144. {
  145. break;
  146. }
  147. }
  148. return frameworkElement as T;
  149. }
  150. /// <summary>
  151. /// 获取父元素
  152. /// </summary>
  153. /// <typeparam name="T">类型</typeparam>
  154. /// <param name="child">子元素</param>
  155. /// <returns>父元素</returns>
  156. public static T TryGetParentFromVisualTree<T>(this FrameworkElement child) where T : FrameworkElement
  157. {
  158. if (child != null && !(child is T))
  159. {
  160. return (VisualTreeHelper.GetParent(child) as FrameworkElement).TryGetParentFromVisualTree<T>();
  161. }
  162. return (T)(object)child;
  163. }
  164. /// <summary>
  165. /// 获取父元素
  166. /// </summary>
  167. /// <typeparam name="T">类型</typeparam>
  168. /// <param name="child">子元素</param>
  169. /// <returns>父元素</returns>
  170. public static T TryGetParentFromVisualTree<T>(this DependencyObject child) where T : DependencyObject
  171. {
  172. if (child != null && !(child is T))
  173. {
  174. return VisualTreeHelper.GetParent(child).TryGetParentFromVisualTree<T>();
  175. }
  176. return (T)(object)child;
  177. }
  178. /// <summary>
  179. /// 遍历子元素
  180. /// </summary>
  181. /// <param name="dependencyObj">依赖对象</param>
  182. /// <param name="childAction">变量方法</param>
  183. internal static void ForEachVisualChild(this DependencyObject dependencyObj, Action<DependencyObject> childAction)
  184. {
  185. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObj); i++)
  186. {
  187. DependencyObject child = VisualTreeHelper.GetChild(dependencyObj, i);
  188. child.ForEachVisualChild(childAction);
  189. childAction.Invoke(child);
  190. }
  191. }
  192. /// <summary>
  193. /// 是否包含子对象
  194. /// </summary>
  195. /// <param name="parent">父元素</param>
  196. /// <param name="dependencyObj">依赖对象</param>
  197. /// <returns>结果</returns>
  198. public static bool ContainsChild(this DependencyObject parent, DependencyObject dependencyObj)
  199. {
  200. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
  201. {
  202. DependencyObject child = VisualTreeHelper.GetChild(parent, i);
  203. if (child == dependencyObj || child.ContainsChild(dependencyObj))
  204. {
  205. return true;
  206. }
  207. }
  208. return false;
  209. }
  210. /// <summary>
  211. /// 获取依赖属性的值
  212. /// </summary>
  213. /// <typeparam name="T">类型</typeparam>
  214. /// <param name="reference">对象</param>
  215. /// <param name="property">属性</param>
  216. /// <returns>属性的值</returns>
  217. public static T GetAncestorValue<T>(this DependencyObject reference, DependencyProperty property)
  218. {
  219. T result = default;
  220. while (reference != null && (result = ObjectExtension.AssertCast<T>(reference.GetValue(property))) == null)
  221. {
  222. DependencyObject parent = VisualTreeHelper.GetParent(reference);
  223. if (parent == null)
  224. {
  225. FrameworkElement frameworkElement = reference as FrameworkElement;
  226. if (frameworkElement != null)
  227. {
  228. parent = frameworkElement.Parent;
  229. }
  230. }
  231. reference = parent;
  232. }
  233. return result;
  234. }
  235. }
  236. }