2008-10-14 58 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创建子控件,则应分别在控件创建和销毁时始终触发它们。