3

Intention is to get and handle Routed Events from child Window. I cannot (read: do not want to) use direct routing as there are more elements between (a Command).

The following example demonstrates that Event Routing is not working from one Window to second Window. Child window XAML:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
<Grid>
    <Button Content="Raise Routing Event" HorizontalAlignment="Left" Margin="50" VerticalAlignment="Top"
            Width="150" Click="RaiseRoutedEvent" />
</Grid>

Raise Event Code:

using System.Windows;

namespace WpfApplication1
{
    public partial class Window1
    {
        private static readonly RoutedEvent ChildWindowEvent = EventManager.RegisterRoutedEvent("ButtonClicked",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Window1));

        public Window1()
        {
            InitializeComponent();
        }

        public event RoutedEventHandler ButtonClicked
        {
            add { AddHandler(ChildWindowEvent, value); }
            remove { RemoveHandler(ChildWindowEvent, value); }
        }

        private void RaiseRoutedEvent(object sender, RoutedEventArgs e)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(ChildWindowEvent);
            RaiseEvent(eventArgs);
        }
    }
}

Main window:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525" wpfApplication1:Window1.ButtonClicked="HandleRoutedEvent">
    <Grid>
        <Button Content="Open new window" HorizontalAlignment="Left" Margin="50" VerticalAlignment="Top"
                Width="150" Click="OpenNewWindow" />
    </Grid>
</Window>

Window which should handle the routed event:

using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OpenNewWindow(object sender, RoutedEventArgs e)
        {
            Window1 window1 = new Window1();
            window1.ShowDialog();
        }

        private void HandleRoutedEvent(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("This message is shown from the Main Window");
        }
    }
}

The event is raised from Window1 but the MainWindow.HandleRoutedEvent does not hit its break point. Why?

J Pollack
  • 2,788
  • 3
  • 29
  • 43

1 Answers1

4

Routed Events travel along the visual tree. A top-level window is a visual tree root and is not part of its owner's visual tree. Therefore, any events which bubble up from within a child window will not propagate up to the owner window.

As an aside, I noticed a couple issues in your example code. In your xaml, you register a handler with attached event syntax, but you have declared an instance event. If you want to implement an attached event, you will need these members:

public static readonly RoutedEvent ButtonClickedEvent = EventManager.RegisterCrossWindowRoutedEvent(
    "ButtonClicked",
    RoutingStrategy.Bubble,
    typeof(RoutedEventHandler),
    typeof(ChildWindow));

public static void AddButtonClickedHandler(UIElement target, RoutedEventHandler handler)
{
    target.AddHandler(ButtonClickedEvent, handler);
}

public static void RemoveButtonClickedHandler(UIElement target, RoutedEventHandler handler)
{
    target.RemoveHandler(ButtonClickedEvent, handler);
}

If you intended to have an instance event, the event name should correspond with the name provided when registering the routed event ("ButtonClicked").

Mike Strobel
  • 25,075
  • 57
  • 69
  • Thanks for the explanation. I understand that tree root is not the same thing as owner. Still, can Owner handle events from child? – J Pollack Oct 29 '13 at 10:33
  • Routed events will not be routed from a child window to its parent, so the code you have written will not work out of the box. You can, however, forward the events yourself. I will extend my answer with an example of how to enable this behavior automatically for custom events. – Mike Strobel Oct 29 '13 at 10:38
  • Scratch that last part. The idea I had didn't quite pan out. Best to just register handlers directly. – Mike Strobel Oct 29 '13 at 10:57
  • Okay thanks. I am discovering about Weak Events and Weak References. There is a pattern: http://msdn.microsoft.com/en-us/library/aa970850.aspx Not sure if that helps me – J Pollack Oct 29 '13 at 11:01
  • What is the 'CrossWindowEventManager'? :) How would the AddXHandler and RemoveXHandler be used? Sorry for my ignorance – J Pollack Oct 29 '13 at 14:19
  • 1
    Whoops, it is a remnant from my earlier experiment :). It should have just been `EventManager`. The AddHandler/RemoveHandler methods are used by the Xaml parser for managing attached event handler subscriptions (like in your example: `wpfApplication1:Window1.ButtonClicked="HandleRoutedEvent"`). – Mike Strobel Oct 29 '13 at 14:29