2008-10-14 56 views
14

我目前正在尋找一種方法,以便在兒童添加到視覺或邏輯子項時進行通知。視覺/邏輯子項添加/刪除時通知

我知道的視覺:: OnVisualChildrenChanged方法,但它並不適用於我,因爲我不能始終繼承和覆蓋此功能。我正在尋找一個事件。

那麼,有沒有一個FrameworkElement的/視覺的老闆當孩子被添加到被通知的方式?

回答

1

我認爲FrameworkElement.LoadedFrameworkElement.Unloaded分別被添加到可視樹和從可視樹中刪除時觸發。然而,有幾次我試圖對它們做任何事情時,我無法讓它們始終如一地被觸發(我當時正在使用類事件處理程序,因此可能與它有關)。

+0

那麼,孩子本身會收到FrameworkElement.Loaded,但父母並不知道孩子實際上已經創建並添加到它。 – decasteljau 2008-10-18 16:31:53

1

也許這將是值得添加到子字段保存參考家長和變更後發送通知回嗎?

1

編輯:

我只是想到了一些東西。如果你能夠設置出現在你的視覺樹中的每個元素上的加載處理,或許可以用這樣的技術進行(認爲這是一個非常基本的想法,就像對一個可能的解決方案開始):

public class ElementChildrenChangedEventArgs 
{ 
    public ElementChildrenChangedEventArgs(FrameworkElement parent, FrameworkElement child) 
    { 
     Parent = parent; 
     Child = child; 
    } 

    public FrameworkElement Parent { get; private set;} 
    public FrameworkElement Child { get; private set;} 
} 

public delegate void ChildrenChanged(ElementChildrenChangedEventArgs args); 

public static class ElementLoadedManager 
{ 
    private static readonly HashSet<FrameworkElement> elements = new HashSet<FrameworkElement>(); 

    public static void Process_Loaded(FrameworkElement fe) 
    { 
     FrameworkElement feParent = VisualTreeHelper.GetParent(fe) as FrameworkElement; 

     if (feParent != null) 
     { 
      if (elements.Contains(feParent)) 
      { 
       InvokeChildrenChanged(feParent, fe); 
      } 
     } 

     if (!elements.Contains(fe)) 
     { 
      elements.Add(fe); 
     } 

     fe.Unloaded += Element_Unloaded;   
    } 

    static void Element_Unloaded(object sender, RoutedEventArgs e) 
    { 
     FrameworkElement fe = sender as FrameworkElement; 
     elements.Remove(fe); 
     ClearUnloaded(fe); 
    } 

    static void ClearUnloaded(FrameworkElement fe) 
    { 
     fe.Unloaded -= Element_Unloaded; 
    } 

    public static event ChildrenChanged ChildrenChanged; 

    private static void InvokeChildrenChanged(FrameworkElement parent, FrameworkElement child) 
    { 
     ElementChildrenChangedEventArgs args = new ElementChildrenChangedEventArgs(parent, child); 

     ChildrenChanged changed = ChildrenChanged; 

     if (changed != null) changed(args); 
    } 
} 

想法(和要求)將在每個元素的Loaded處理函數中調用Process_Loaded(FrameworkElement)方法,這可能會在樣式/模板設置中執行。

而且,由於加載的是一個路由事件,你可以設置只對父窗口的處理程序,並檢查e.OriginalSource。

+0

編輯答案與一些想法。 – 2009-07-12 10:54:01

2

是不是更容易擴展

System.Windows.Controls.UIElementCollection 

做的通知,並使用

protected override UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent) 

1

你可以以提高附加事件從子元素到其父冒泡使用的子元素的附加行爲。或者,在孩子的加載事件中,您可以簡單地在邏輯樹上搜索父代,然後在那裏調用方法或設置一個屬性(例如,遞增一個孩子數),以表示孩子在那裏,取決於你想在父母身上發生什麼。如果你使用方法設置屬性,你也必須處理Unloaded。

加載和卸載並不總是如預期的那樣升高。但是,如果使用DataTemplates創建子控件,則應分別在控件創建和銷燬時始終觸發它們。