0

I am currently working on a custom Panel implementation (based on Canvas) with a specific behavior.

As I need to make several actions depending on child properties. In order to implement the control, I also developed specific child control (based on ContentControl) with some dependency properties, to set up the child option directly in the xaml.

As I also need to make verification at the AddChild call, I intercept the AddChild call by defining the [ContentProperty("NotifiableChildren")] attribute on my Control and then make some checks before adding the child to the Canvas children.

    public interface INotifiableParent
    {
        int AddChild(UIElement child);
        void RemoveChild(UIElement child);
    }

    [ContentProperty("NotifiableChildren")]
    public class MyPanel : Canvas, INotifiableParent
    {
        public MyPanel()
        {
            NotifiableChildren = new NotifiableUIElementCollection(this, this);
        }

        public NotifiableUIElementCollection NotifiableChildren { get; }


        #region INotifiableParent members

        public int AddChild(UIElement child)
        {
            // Add your custom code here

            // Add the child to the InternalChildren
            return this.Children.Add(child);
        }

        public void RemoveChild(UIElement child)
        {
            this.Children.Remove(child);
        }

        #endregion
    }

It works fine, expects during the AddChild call, all my child are not completely initialized. Each instance is created and not null, but all dependency properties are not initialized (I have the same behavior with framework native controls). You can see below the corresponding xaml example with native controls.

<Window x:Class="ProtoPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ProtoPanel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:MyPanel>
            <Rectangle Fill="Aqua"
                       Width="200"
                       Height="100"/>
            <Ellipse Fill="Bisque" 
                     Canvas.Left="300"
                     Canvas.Top="150"
                     Height="100"
                     Width="100"></Ellipse>
        </local:MyPanel>
    </Grid>
</Window>

I put some breakpoints in my custom ContentControls and I saw that all dependency properties (Fill, Width, Heigth, ...) are initialized with xaml values after the child being added to the Canvas.

Does anyone knows if there is a way/trick to have these dep properties initialized at AddChild call ?

Thanks in advance

  • Welcome to Stack Overflow. Sometimes we can guess at the problem without seeing the code, but usually guessing turns into an endless back and forth that's a great waste of everybody's time and patience. It's much easier if you show us your code. You can edit your question and add the code, as text (never a screenshot). I suspect you just need to handle a later event, like `Loaded` or something. But that's just a guess. – 15ee8f99-57ff-4f92-890c-b56153 Oct 07 '19 at 13:18
  • Thanks Ed for your comment. I will add some code today – Jean-Charles DURAND Oct 08 '19 at 07:19
  • So if you handle the Loaded event on MyPanel, you can loop through `Children` there and you'll find them fully initialized at that point. I confirmed this by handling that event your own code. There's no way to trick anything: Initialization happens in the order it happens in. You could give each child a `Loaded` handler in `AddChild()`, and do whatever you want to do in those `Loaded` handlers. – 15ee8f99-57ff-4f92-890c-b56153 Oct 08 '19 at 17:26

0 Answers0