RoutedEvent raised from Unloaded event handler not bubbling

474 views Asked by At

I have a custom user control that inherits from ItemsControl. Via it's ItemTemplate it creates a ChildControl for each attached ViewModel from an ObservableCollection.

public class ChildControl : FrameworkElement
{
    public static readonly RoutedEvent CreatedEvent = EventManager.RegisterRoutedEvent(
        nameof(Created),
        RoutingStrategy.Bubble,
        typeof(RoutedEventHandler),
        typeof(ChildControl));

    public static readonly RoutedEvent RemovedEvent = EventManager.RegisterRoutedEvent(
        nameof(Removed),
        RoutingStrategy.Bubble,
        typeof(RoutedEventHandler),
        typeof(ChildControl));

    public ChildControl
    {
        Loaded += OnLoaded;
        Unloaded += OnUnloaded;
    }

    public event RoutedEventHandler Created
    {
        add => AddHandler(CreatedEvent, value);
        remove => RemoveHandler(CreatedEvent, value);
    }

    public event RoutedEventHandler Removed
    {
        add => AddHandler(RemovedEvent, value);
        remove => RemoveHandler(RemovedEvent, value);
    }

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        RaiseEvent(new RoutedEventArgs(CreatedEvent));
    }

    private void OnUnloaded(object sender, RoutedEventArgs e)
    {
        RaiseEvent(new RoutedEventArgs(RemovedEvent));
    }
}

And the CustomItemsControl

public class CustomItemsControl : ItemsControl
{
    public CustomItemsControl()
    {
        AddHandler(ChildControl.CreatedEvent, new RoutedEventHandler(OnCreatedEvent));
        AddHandler(ChildControl.RemovedEvent, new RoutedEventHandler(OnRemovedEvent));
    }
    
    private void OnCreatedEvent(object sender, RoutedEventArgs e)
    {
        // stuff
    }

    private void OnRemovedEvent(object sender, RoutedEventArgs e)
    {
        // stuff
    }
}

Everything works fine apart from the RemovedEvent handler. When the event is raised inside Unloaded event handler of ChildControl, then it is not being caught by the CustomItemsControl. However, when the RemovedEvent is called let's say in Loaded event handler, then it is being caught by CustomItemsControl. So it proves that everything is hooked up fine.

Have I done something wrong or does it mean that RoutedEvents called from within Unloaded event handler are not being bubbled by design?

1

There are 1 answers

0
Andy On BEST ANSWER

The thing is gone.

But you still expect to hear it.

Re-consider the Unloaded event. Think about what's happened.

"Occurs when the element is removed from within an element tree of loaded elements."

https://learn.microsoft.com/en-us/dotnet/api/system.windows.frameworkelement.unloaded?view=netcore-3.1https://learn.microsoft.com/en-us/dotnet/api/system.windows.frameworkelement.unloaded?view=netcore-3.1

It's gone.

As in not there.

Not in any visual tree, not in anything.

Because it was unloaded from the UI.

A routed event from it cannot bubble or tunnel or anything that involves the visual tree. Because the uielement is no longer in that tree.

What you'd need to do is raise a custom routed event first, then unload your control. Maybe using a different approach entirely would be a better way to go. Examples include: prism eventaggregator or mvvmlight messenger or passing a reference from parent to child so it can call a method directly.