LinqToVisualTree.cs (11916B)
1 using System; 2 using System.Linq; 3 using System.Collections.Generic; 4 using System.Windows; 5 using System.Windows.Media; 6 7 namespace LinqToVisualTree 8 { 9 /// <summary> 10 /// Adapts a DependencyObject to provide methods required for generate 11 /// a Linq To Tree API 12 /// </summary> 13 public class VisualTreeAdapter : ILinqTree<DependencyObject> 14 { 15 private DependencyObject _item; 16 17 public VisualTreeAdapter(DependencyObject item) 18 { 19 _item = item; 20 } 21 22 public IEnumerable<DependencyObject> Children() 23 { 24 int childrenCount = VisualTreeHelper.GetChildrenCount(_item); 25 for (int i = 0; i < childrenCount; i++) 26 { 27 yield return VisualTreeHelper.GetChild(_item, i); 28 } 29 } 30 31 public DependencyObject Parent 32 { 33 get 34 { 35 return VisualTreeHelper.GetParent(_item); 36 } 37 } 38 } 39 } 40 41 namespace LinqToVisualTree 42 { 43 /// <summary> 44 /// Defines an interface that must be implemented to generate the LinqToTree methods 45 /// </summary> 46 /// <typeparam name="T"></typeparam> 47 public interface ILinqTree<T> 48 { 49 IEnumerable<T> Children(); 50 51 T Parent { get; } 52 } 53 54 public static class TreeExtensions 55 { 56 /// <summary> 57 /// Returns a collection of descendant elements. 58 /// </summary> 59 public static IEnumerable<DependencyObject> Descendants(this DependencyObject item) 60 { 61 ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item); 62 foreach (var child in adapter.Children()) 63 { 64 yield return child; 65 66 foreach (var grandChild in child.Descendants()) 67 { 68 yield return grandChild; 69 } 70 } 71 } 72 73 /// <summary> 74 /// Returns a collection containing this element and all descendant elements. 75 /// </summary> 76 public static IEnumerable<DependencyObject> DescendantsAndSelf(this DependencyObject item) 77 { 78 yield return item; 79 80 foreach (var child in item.Descendants()) 81 { 82 yield return child; 83 } 84 } 85 86 /// <summary> 87 /// Returns a collection of ancestor elements. 88 /// </summary> 89 public static IEnumerable<DependencyObject> Ancestors(this DependencyObject item) 90 { 91 ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item); 92 93 var parent = adapter.Parent; 94 while (parent != null) 95 { 96 yield return parent; 97 adapter = new VisualTreeAdapter(parent); 98 parent = adapter.Parent; 99 } 100 } 101 102 /// <summary> 103 /// Returns a collection containing this element and all ancestor elements. 104 /// </summary> 105 public static IEnumerable<DependencyObject> AncestorsAndSelf(this DependencyObject item) 106 { 107 yield return item; 108 109 foreach (var ancestor in item.Ancestors()) 110 { 111 yield return ancestor; 112 } 113 } 114 115 /// <summary> 116 /// Returns a collection of child elements. 117 /// </summary> 118 public static IEnumerable<DependencyObject> Elements(this DependencyObject item) 119 { 120 ILinqTree<DependencyObject> adapter = new VisualTreeAdapter(item); 121 foreach (var child in adapter.Children()) 122 { 123 yield return child; 124 } 125 } 126 127 /// <summary> 128 /// Returns a collection of the sibling elements before this node, in document order. 129 /// </summary> 130 public static IEnumerable<DependencyObject> ElementsBeforeSelf(this DependencyObject item) 131 { 132 if (item.Ancestors().FirstOrDefault() == null) 133 yield break; 134 foreach (var child in item.Ancestors().First().Elements()) 135 { 136 if (child.Equals(item)) 137 break; 138 yield return child; 139 } 140 } 141 142 /// <summary> 143 /// Returns a collection of the after elements after this node, in document order. 144 /// </summary> 145 public static IEnumerable<DependencyObject> ElementsAfterSelf(this DependencyObject item) 146 { 147 if (item.Ancestors().FirstOrDefault() == null) 148 yield break; 149 bool afterSelf = false; 150 foreach (var child in item.Ancestors().First().Elements()) 151 { 152 if (afterSelf) 153 yield return child; 154 155 if (child.Equals(item)) 156 afterSelf = true; 157 } 158 } 159 160 /// <summary> 161 /// Returns a collection containing this element and all child elements. 162 /// </summary> 163 public static IEnumerable<DependencyObject> ElementsAndSelf(this DependencyObject item) 164 { 165 yield return item; 166 167 foreach (var child in item.Elements()) 168 { 169 yield return child; 170 } 171 } 172 173 /// <summary> 174 /// Returns a collection of descendant elements which match the given type. 175 /// </summary> 176 public static IEnumerable<DependencyObject> Descendants<T>(this DependencyObject item) 177 { 178 return item.Descendants().Where(i => i is T).Cast<DependencyObject>(); 179 } 180 181 /// <summary> 182 /// Returns a collection of the sibling elements before this node, in document order 183 /// which match the given type. 184 /// </summary> 185 public static IEnumerable<DependencyObject> ElementsBeforeSelf<T>(this DependencyObject item) 186 { 187 return item.ElementsBeforeSelf().Where(i => i is T).Cast<DependencyObject>(); 188 } 189 190 /// <summary> 191 /// Returns a collection of the after elements after this node, in document order 192 /// which match the given type. 193 /// </summary> 194 public static IEnumerable<DependencyObject> ElementsAfterSelf<T>(this DependencyObject item) 195 { 196 return item.ElementsAfterSelf().Where(i => i is T).Cast<DependencyObject>(); 197 } 198 199 /// <summary> 200 /// Returns a collection containing this element and all descendant elements 201 /// which match the given type. 202 /// </summary> 203 public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this DependencyObject item) 204 { 205 return item.DescendantsAndSelf().Where(i => i is T).Cast<DependencyObject>(); 206 } 207 208 /// <summary> 209 /// Returns a collection of ancestor elements which match the given type. 210 /// </summary> 211 public static IEnumerable<DependencyObject> Ancestors<T>(this DependencyObject item) 212 { 213 return item.Ancestors().Where(i => i is T).Cast<DependencyObject>(); 214 } 215 216 /// <summary> 217 /// Returns a collection containing this element and all ancestor elements 218 /// which match the given type. 219 /// </summary> 220 public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this DependencyObject item) 221 { 222 return item.AncestorsAndSelf().Where(i => i is T).Cast<DependencyObject>(); 223 } 224 225 /// <summary> 226 /// Returns a collection of child elements which match the given type. 227 /// </summary> 228 public static IEnumerable<DependencyObject> Elements<T>(this DependencyObject item) 229 { 230 return item.Elements().Where(i => i is T).Cast<DependencyObject>(); 231 } 232 233 /// <summary> 234 /// Returns a collection containing this element and all child elements. 235 /// which match the given type. 236 /// </summary> 237 public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this DependencyObject item) 238 { 239 return item.ElementsAndSelf().Where(i => i is T).Cast<DependencyObject>(); 240 } 241 242 } 243 244 public static class EnumerableTreeExtensions 245 { 246 /// <summary> 247 /// Applies the given function to each of the items in the supplied 248 /// IEnumerable. 249 /// </summary> 250 private static IEnumerable<DependencyObject> DrillDown(this IEnumerable<DependencyObject> items, 251 Func<DependencyObject, IEnumerable<DependencyObject>> function) 252 { 253 foreach (var item in items) 254 { 255 foreach (var itemChild in function(item)) 256 { 257 yield return itemChild; 258 } 259 } 260 } 261 262 /// <summary> 263 /// Applies the given function to each of the items in the supplied 264 /// IEnumerable, which match the given type. 265 /// </summary> 266 public static IEnumerable<DependencyObject> DrillDown<T>(this IEnumerable<DependencyObject> items, 267 Func<DependencyObject, IEnumerable<DependencyObject>> function) 268 where T : DependencyObject 269 { 270 foreach (var item in items) 271 { 272 foreach (var itemChild in function(item)) 273 { 274 if (itemChild is T) 275 { 276 yield return (T)itemChild; 277 } 278 } 279 } 280 } 281 282 /// <summary> 283 /// Returns a collection of descendant elements. 284 /// </summary> 285 public static IEnumerable<DependencyObject> Descendants(this IEnumerable<DependencyObject> items) 286 { 287 return items.DrillDown(i => i.Descendants()); 288 } 289 290 /// <summary> 291 /// Returns a collection containing this element and all descendant elements. 292 /// </summary> 293 public static IEnumerable<DependencyObject> DescendantsAndSelf(this IEnumerable<DependencyObject> items) 294 { 295 return items.DrillDown(i => i.DescendantsAndSelf()); 296 } 297 298 /// <summary> 299 /// Returns a collection of ancestor elements. 300 /// </summary> 301 public static IEnumerable<DependencyObject> Ancestors(this IEnumerable<DependencyObject> items) 302 { 303 return items.DrillDown(i => i.Ancestors()); 304 } 305 306 /// <summary> 307 /// Returns a collection containing this element and all ancestor elements. 308 /// </summary> 309 public static IEnumerable<DependencyObject> AncestorsAndSelf(this IEnumerable<DependencyObject> items) 310 { 311 return items.DrillDown(i => i.AncestorsAndSelf()); 312 } 313 314 /// <summary> 315 /// Returns a collection of child elements. 316 /// </summary> 317 public static IEnumerable<DependencyObject> Elements(this IEnumerable<DependencyObject> items) 318 { 319 return items.DrillDown(i => i.Elements()); 320 } 321 322 /// <summary> 323 /// Returns a collection containing this element and all child elements. 324 /// </summary> 325 public static IEnumerable<DependencyObject> ElementsAndSelf(this IEnumerable<DependencyObject> items) 326 { 327 return items.DrillDown(i => i.ElementsAndSelf()); 328 } 329 330 /// <summary> 331 /// Returns a collection of descendant elements which match the given type. 332 /// </summary> 333 public static IEnumerable<DependencyObject> Descendants<T>(this IEnumerable<DependencyObject> items) 334 where T : DependencyObject 335 { 336 return items.DrillDown<T>(i => i.Descendants()); 337 } 338 339 /// <summary> 340 /// Returns a collection containing this element and all descendant elements. 341 /// which match the given type. 342 /// </summary> 343 public static IEnumerable<DependencyObject> DescendantsAndSelf<T>(this IEnumerable<DependencyObject> items) 344 where T : DependencyObject 345 { 346 return items.DrillDown<T>(i => i.DescendantsAndSelf()); 347 } 348 349 /// <summary> 350 /// Returns a collection of ancestor elements which match the given type. 351 /// </summary> 352 public static IEnumerable<DependencyObject> Ancestors<T>(this IEnumerable<DependencyObject> items) 353 where T : DependencyObject 354 { 355 return items.DrillDown<T>(i => i.Ancestors()); 356 } 357 358 /// <summary> 359 /// Returns a collection containing this element and all ancestor elements. 360 /// which match the given type. 361 /// </summary> 362 public static IEnumerable<DependencyObject> AncestorsAndSelf<T>(this IEnumerable<DependencyObject> items) 363 where T : DependencyObject 364 { 365 return items.DrillDown<T>(i => i.AncestorsAndSelf()); 366 } 367 368 /// <summary> 369 /// Returns a collection of child elements which match the given type. 370 /// </summary> 371 public static IEnumerable<DependencyObject> Elements<T>(this IEnumerable<DependencyObject> items) 372 where T : DependencyObject 373 { 374 return items.DrillDown<T>(i => i.Elements()); 375 } 376 377 /// <summary> 378 /// Returns a collection containing this element and all child elements. 379 /// which match the given type. 380 /// </summary> 381 public static IEnumerable<DependencyObject> ElementsAndSelf<T>(this IEnumerable<DependencyObject> items) 382 where T : DependencyObject 383 { 384 return items.DrillDown<T>(i => i.ElementsAndSelf()); 385 } 386 } 387 }