file360

Log | Files | Refs

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 }