WPF - How to detect when new Visual child elements are added?

Jerry Nixon picture Jerry Nixon · May 17, 2011 · Viewed 11.7k times · Source

Based on some custom security settings, I alter window child controls to readonly and disabled. To accomplish this, I loop through child controls when the window loads.

This works just fine. 99% perfect.

In my window I have an ItemsControl whose content is based on a ComboBox. Change the ComboBox, the child controls in the ItemsControl are databound again. But, then security (readonly/disabled) is no longer true.

Before you jump to the solution, I know I could handle the ComboBox changed event; but, I have many such boxes and wnt a generic solution to can apply at the window-level (think: base) no matter what my developers add to the window/form.

My question (sorry for the long lead in) is, how can I detect when a new child is added to the window because of some dynamic activity like databinding? Is there a NewChildAdded event? Is there a DataBindingJustChangedThings event?

There's gotta be something.

If your solution includes a timer, you need not reply. My forms are too complex to handle that extra load - and the delay between ticks is too real of a security issue.

You might be thinking, just make the outer-container readonly or disabled. But this has a negative effect on things like expanders, multi-line textboxes and listboxes. Such an approach is not grainular enough. Of course, it is where we started iterations ago.

If your solution includes a style, you need to include how I can override your approach on a per-control basis. Some controls (like a checkbox) cannot be disabled as they have a purpose in the UI layout.

Sorry for the constraints, but I plan to use the solution in production.

Thank you.

Answer

Ed Bayiates picture Ed Bayiates · May 17, 2011

Have you tried OnVisualChildrenChanged?

    /// <summary>
    /// Handle visual children being added or removed
    /// </summary>
    /// <param name="visualAdded">Visual child added</param>
    /// <param name="visualRemoved">Visual child removed</param>
    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        // Track when objects are added and removed
        if (visualAdded != null)
        {
            // Do stuff with the added object
        }
        if (visualRemoved != null)
        {
            // Do stuff with the removed object
        }

        // Call base function
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);
    }