2010-12-13 87 views
4

現在這可能比它的價值更麻煩,但儘管如此,它現在對我來說真的很有用。Silverlight&Visual Tree Manipulation

我想知道的是如何在運行時操縱Silverlight可視化樹。做簡單的事情,比如添加和刪除控件很容易,但是當你開始必須以合理的複雜度遍歷樹時,我發現自己渴望用於處理DOM節點替換的JQuery樣式語法(LINQ將會非常酷) ,運動等。

所以我想問的是,有沒有什麼圖書館讓這個工作變得更容易,或者有沒有烤過的東西,我錯過了?

回答

6

是LINQ的擴展方法是你所追求的,但你必須首先把就地豆蔻基礎設施: -

public static class VisualTreeEnumeration 
{ 
    public static IEnumerable<DependencyObject> Descendents(this DependencyObject root, int depth) 
    { 
     int count = VisualTreeHelper.GetChildrenCount(root); 
     for (int i = 0; i < count; i++) 
     { 
      var child = VisualTreeHelper.GetChild(root, i); 
      yield return child; 
      if (depth > 0) 
      { 
       foreach (var descendent in Descendents(child, --depth)) 
        yield return descendent; 
      } 
     } 
    } 

    public static IEnumerable<DependencyObject> Descendents(this DependencyObject root) 
    { 
      return Descendents(root, Int32.MaxValue); 
    } 

    public static IEnumerable<DependencyObject> Ancestors(this DependencyObject root) 
    { 
      DependencyObject current = VisualTreeHelper.GetParent(root); 
      while (current != null) 
      { 
       yield return current; 
       current = VisualTreeHelper.GetParent(current); 
      } 
    } 
} 

現在你可以使用LINQ查詢到使用LINQ可視化樹。一些例子: -

// Get all text boxes in usercontrol:- 
this.Descendents().OfType<TextBox>(); 

// All UIElement direct children of the layout root grid:- 
LayoutRoot.Descendents(0).OfType<UIElement>(); 

// Find the containing `ListBoxItem` for an element:- 
elem.Ancestors().OfType<ListBoxItem>.FirstOrDefault(); 

// Seek button with name "PinkElephants" even if outside of the current Namescope:- 
this.Descendents() 
    .OfType<Button>() 
    .FirstOrDefault(b => b.Name == "PinkElephants"); 
+0

真棒...感謝一大堆。 – Stimul8d 2010-12-13 13:51:11

0

什麼版本的silverlight是這樣的? 「12月13日13:13」是哪一年?

在當前版本SL4它似乎並沒有在那裏

..

0

我用這個代碼從可視樹得到控制

public static FrameworkElement GetComponent(object child, Type t, Type bailOn) 
    { 
     if (child == null) return null; 

     DependencyObject control = (DependencyObject)child; // VisualTreeHelper.GetParent((DependencyObject)x); 

     while (control != null) 
     { 
      if (!control.Equals(child)) 
      { 
       if (control.GetType() == t) 
       { 
        break; 
       } 
      } 

      if (control is FrameworkElement) 
      { 
       control = (control as FrameworkElement).Parent; 
      } 
      else if ((control is DataGridBoundColumn)) // data grid fucken columns 
      { 
       control = GetDataGridBoundColumnDataGrid(control); 

      } 
      if (control != null && bailOn != null && bailOn.GetType() == control.GetType()) 
      { 
       return null; 
      } 

     } 

     // try VTH as we did not find it, as that works some times and the above does not 
     if (control == null) 
     { 
      control = (DependencyObject)child; // start again 

      while (control != null) 
      { 
       if (!control.Equals(child)) 
       { 
        if (control.GetType() == t) 
        { 
         break; 
        } 
       } 
       if (control is FrameworkElement) 
       { 
        control = VisualTreeHelper.GetParent((control as FrameworkElement)); 
       } 
       else if (control is DataGridBoundColumn) 
       { 
        control = GetDataGridBoundColumnDataGrid(control); 
       } 

       if (control != null && bailOn != null && bailOn.GetType() == control.GetType()) 
       { 
        return null; 
       } 

      } 

     } 
     return control as FrameworkElement; 
    } 

    public static List<FrameworkElement> GetComponentsByType(FrameworkElement parent, Type type) 
    { 
     List<FrameworkElement> controls = new List<FrameworkElement>(); 
     GetComponentsByTypeWorker(parent, type, controls); 
     return controls; 

    } 
    private static void GetComponentsByTypeWorker(FrameworkElement parent, Type type, List<FrameworkElement> controls) 
    { 

     if (parent.GetType() == type) 
     { 
      controls.Add(parent as FrameworkElement); 
     } 

     int cnt = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < cnt; i++) 
     { 
      FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement; 
      if (child.GetType() == type) 
      { 
       controls.Add(child as FrameworkElement); 
      } 

      int cnt2 = VisualTreeHelper.GetChildrenCount(child); 
      for (int j = 0; j < cnt2; j++) 
      { 
       FrameworkElement child2 = VisualTreeHelper.GetChild(child, j) as FrameworkElement; 

       GetComponentsByTypeWorker(child2 as FrameworkElement, type, controls); 
      } 
     } 




    }