none
Detecting when children are added to a Panel

    Question

  • I have a custom panel and I need to perform some action when a child is added to it. This action should happen immediately when it's added -- it can't wait for MeasureOverride or ArrangeOverride to be called. What is the best way to handle this? The Children collection dispatches no events, and I'm not sure how to replace it with an ObservableCollection and still have the panel work properly in XAML.

    Tuesday, October 28, 2008 5:57 PM

Answers

  • You may just have to create a layer of indirection yourself to handle this.  Is it your code that's adding things to the canvas?  Rather than:

    myCanvas.Children.Add(whatever); 

    ... do something like create an extension method:

    public static void AddChild(this Canvas c, UIElement newChild) {

    //do initialization on newChild
    c.Children.Add(newChild);

    }

    myCanvas.AddChild(something);

    Wednesday, October 29, 2008 3:37 PM

All replies

  • You will need to implement the Panel.LayoutUpdated event.  You can go to this link for more information:

    http://msdn.microsoft.com/en-us/library/system.windows.controls.panel_events(VS.95).aspx

     

    (Please mark as Answered if this helps!)  Cool

    Wednesday, October 29, 2008 5:05 AM
  • Thanks for the reply, but that doesn't seem to solve my problem.

    When a child is added to this panel, I need it to immediately perform some initialization work, so that if it is added via code, those initialized properties are available on the next line of code. All of the children of the panel are of the same type, so I can have either the panel or the child do this work.

    In WPF, I do this in the child object by overriding OnVisualParentChanged. Silverlight doesn't seem to have an equivalent.

    Wednesday, October 29, 2008 3:27 PM
  • You may just have to create a layer of indirection yourself to handle this.  Is it your code that's adding things to the canvas?  Rather than:

    myCanvas.Children.Add(whatever); 

    ... do something like create an extension method:

    public static void AddChild(this Canvas c, UIElement newChild) {

    //do initialization on newChild
    c.Children.Add(newChild);

    }

    myCanvas.AddChild(something);

    Wednesday, October 29, 2008 3:37 PM
  • I may need to resort to something like that, but that's somewhat undesireable since the behavior would be different between code and XAML. When the child is added via XAML, that AddChild method wouldn't be called. The best I can do is keep an internal list of children and compare it with the Children property in OnMeasureOverride.

     Thanks though, I guess I'll move down that path.

    Wednesday, October 29, 2008 3:45 PM
  • Yeah, I suppose so, but its only slightly more work.  You can check the initial/XAML state one time on Loaded, and use the extension method in other cases.

    Wednesday, October 29, 2008 3:55 PM
  • "The best I can do is keep an internal list of children and compare it with the Children property in OnMeasureOverride" 

    Went down that route, and came up with the following solution:

    http://skysigal.xact-solutions.com/Blog/tabid/427/Default.aspx

     

    Sunday, January 24, 2010 2:47 AM
  • I have have a solution that works really well for those who may wander by here. The 'Children' property is actually found by the parser using the "ContentProperty" attribute, and I think it's inheritable. Anyhow, if you simply put this in your derived class:

            new public ObservableCollection<UIElement> Children { get { return _Children; } }
            readonly ObservableCollection<UIElement> _Children = new ObservableCollection<UIElement>();

    Then all the added elements will now go to this new collection instead! :) All you have to do it listen to the "CollectionChanged" event.

    Cheers!Cool

    (Blog post: http://jameswilkins.net/coding/1111/)

    Wednesday, May 30, 2012 3:51 AM