从最近做的一个WPF项目中勾出来的,对VisualTreeHelper的扩展,用于视觉树节点的查找.
ps:这里有些在WPF中需要清楚
1.视觉树不等于逻辑树,WPF的树概念可以参考http://msdn.microsoft.com/zh-cn/library/vstudio/ms753391(v=vs.90).aspx
2.ApplyTemplate方法用于视觉树的重建,在执行某些操作时(例如查找某个树节点时候)可能因为视觉树未创建导致查找失败,所以可以通过该方法来确保视觉树完成
扩展VisualTreeHelperEx
class="code_img_closed" src="/Upload/Images/2013082621/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('452f9aa4-29f9-428a-b09d-b9641a2a7616',event)" src="/Upload/Images/2013082621/2B1B950FA3DF188F.gif" alt="" />1 public class VisualTreeHelperEx { 2 /// <summary> 3 /// 从指定的树,查找第一个名称等于findChildName的元素 4 /// ps:多用于自定义模板中无法直接通过GetChildTemplate直接 5 /// 查找的,例如DataTemplate 6 /// </summary> 7 /// <typeparam name="T"></typeparam> 8 /// <param name="targetStartDPObj"></param> 9 /// <param name="findChildName"></param> 10 /// <returns></returns> 11 public static T FindFirstVisualChild<T>(DependencyObject targetStartDPObj, string findChildName) 12 where T : DependencyObject { 13 int iChildCount = VisualTreeHelper.GetChildrenCount(targetStartDPObj); 14 for (int i = 0; i < iChildCount; i++) { 15 DependencyObject childObj = VisualTreeHelper.GetChild(targetStartDPObj, i); 16 if (childObj != null && 17 childObj is T && 18 childObj.GetValue(FrameworkElement.NameProperty).ToString().Equals(findChildName)) { 19 return (T)childObj; 20 } 21 else { 22 //如果当前节点存在二级树那么继续向下查找 23 T childOfChild = FindFirstVisualChild<T>(childObj, findChildName); 24 if (childOfChild != null) { 25 return childOfChild; 26 } 27 } 28 } 29 30 return null; 31 } 32 33 /// <summary> 34 /// 查找父节点,包含自身 35 /// </summary> 36 /// <param name="targetDpObj"></param> 37 /// <param name="type">指定查找的目标类型</param> 38 /// <param name="noFindChildType">查找时候是否考虑到该类型的派生类型</param> 39 /// <returns></returns> 40 public static DependencyObject FindAncestorByType(DependencyObject targetDpObj, Type type, bool noFindChildType) { 41 if (targetDpObj == null) { 42 return null; 43 } 44 45 if (noFindChildType ? (targetDpObj.GetType() == type) : ((targetDpObj.GetType() == type) || 46 targetDpObj.GetType().IsSubclassOf(type))) { 47 return targetDpObj; 48 } 49 50 return FindAncestorByType(GetParent(targetDpObj), type, noFindChildType); 51 } 52 /// <summary> 53 /// 查找父节点 54 /// </summary> 55 /// <typeparam name="T"></typeparam> 56 /// <param name="targetDpObj"></param> 57 /// <returns></returns> 58 public static T FindAncestorByType<T>(DependencyObject targetDpObj) 59 where T : DependencyObject { 60 if (targetDpObj == null) { 61 return default(T); 62 } 63 64 if (targetDpObj is T) { 65 return (T)targetDpObj; 66 } 67 68 T parentObj = default(T); 69 parentObj = FindAncestorByType<T>(GetParent(targetDpObj)); 70 return parentObj; 71 } 72 73 /// <summary> 74 /// 查找指定节点的父节点,向上查找 75 /// 查找时候分别考虑了FramworkElement和FramworkContentElement两种情况 76 /// </summary> 77 /// <param name="targetDPObj"></param> 78 /// <returns></returns> 79 public static DependencyObject GetParent(DependencyObject targetDPObj) { 80 Visual visualElement = targetDPObj as Visual; 81 if (visualElement == null) { 82 return null; 83 } 84 85 DependencyObject parentObj = VisualTreeHelper.GetParent(visualElement); 86 if (parentObj == null) { 87 FrameworkElement frameworkElement = targetDPObj as FrameworkElement; 88 if (frameworkElement != null) { 89 parentObj = frameworkElement.Parent; 90 if (parentObj == null) { 91 parentObj = frameworkElement.TemplatedParent; 92 } 93 } 94 } 95 else { 96 FrameworkContentElement fce = targetDPObj as FrameworkContentElement; 97 if (fce != null) { 98 parentObj = fce.Parent; 99 if (parentObj == null) { 100 parentObj = fce.TemplatedParent; 101 } 102 } 103 } 104 105 return parentObj; 106 } 107 108 /// <summary> 109 /// 查找指定节点,向下查找 110 /// </summary> 111 /// <param name="targetDpObj"></param> 112 /// <param name="type"></param> 113 /// <param name="noFindChildType"></param> 114 /// <returns></returns> 115 public static Visual FindDescendantByType(Visual targetDpObj, Type type, bool noFindChildType) { 116 if (targetDpObj == null) { 117 return null; 118 } 119 120 if (noFindChildType ? (targetDpObj.GetType() == type) : ((targetDpObj.GetType() == type) || (targetDpObj.GetType().IsSubclassOf(type)))) { 121 return targetDpObj; 122 } 123 124 Visual foundedElement = null; 125 if (targetDpObj is FrameworkElement) { 126 //重建树,避免调用该函数前,树还没建立 127 (targetDpObj as FrameworkElement).ApplyTemplate(); 128 } 129 130 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(targetDpObj); i++) { 131 Visual tempvisual = VisualTreeHelper.GetChild(targetDpObj, i) as Visual; 132 foundedElement = FindDescendantByType(tempvisual, type, noFindChildType); 133 if (foundedElement != null) { 134 break; 135 } 136 } 137 138 return foundedElement; 139 } 140 141 /// <summary> 142 /// 通过指定依赖项属性和值查找向下查找指定的节点 143 /// </summary> 144 /// <param name="targetDpObj"></param> 145 /// <param name="dp"></param> 146 /// <param name="value"></param> 147 /// <returns></returns> 148 public static Visual FindDescendantByProperty(Visual targetDpObj, DependencyProperty dp, object value) { 149 if (targetDpObj == null) 150 return null; 151 if (targetDpObj.GetValue(dp).Equals(value)) { 152 return targetDpObj; 153 } 154 155 Visual foundedElement = null; 156 if (targetDpObj is FrameworkElement) { 157 (targetDpObj as FrameworkElement).ApplyTemplate(); 158 } 159 160 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(targetDpObj); i++) { 161 Visual tempvisual = VisualTreeHelper.GetChild(targetDpObj, i) as Visual; 162 foundedElement = FindDescendantByProperty(tempvisual, dp, value); 163 if (foundedElement != null) { 164 break; 165 } 166 } 167 168 return foundedElement; 169 } 170 }View Code