【问题标题】:How to Handle Routed Event From a Child Window如何处理来自子窗口的路由事件
【发布时间】:2013-10-29 09:47:12
【问题描述】:

意图是从子窗口获取和处理路由事件。我不能(阅读:不想)使用直接路由,因为(命令)之间有更多元素。

以下示例说明事件路由无法从一个窗口运行到第二个窗口。 子窗口 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>

引发事件代码:

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);
        }
    }
}

主窗口:

<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>

应该处理路由事件的窗口:

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");
        }
    }
}

该事件是从 Window1 引发的,但 MainWindow.HandleRoutedEvent 未达到其断点。为什么?

【问题讨论】:

    标签: c# wpf routed-events


    【解决方案1】:

    路由事件沿着可视化树传播。顶级窗口是可视树根,不是其所有者可视树的一部分。因此,从子窗口中冒出的任何事件都不会传播到所有者窗口。

    顺便说一句,我注意到您的示例代码中有几个问题。在您的 xaml 中,您使用附加的事件语法注册了一个处理程序,但您已经声明了一个实例事件。如果要实现附加事件,则需要这些成员:

    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);
    }
    

    如果您打算创建实例事件,则事件名称应与注册路由事件时提供的名称相对应(“ButtonClicked”)。

    【讨论】:

    • 感谢您的解释。我知道树根与所有者不同。不过,所有者可以处理来自孩子的事件吗?
    • 路由事件不会从子窗口路由到其父窗口,因此您编写的代码不会开箱即用。但是,您可以自己转发事件。我将通过一个示例来扩展我的答案,说明如何为自定义事件自动启用此行为。
    • 刮掉最后一部分。我的想法并没有完全实现。最好直接注册处理程序。
    • 好的,谢谢。我正在发现有关弱事件和弱引用的信息。有一个模式:msdn.microsoft.com/en-us/library/aa970850.aspx 不确定这是否对我有帮助
    • 哎呀,这是我早期实验的残余物 :)。应该是EventManager。 Xaml 解析器使用 AddHandler/RemoveHandler 方法来管理附加的事件处理程序订阅(例如在您的示例中:wpfApplication1:Window1.ButtonClicked="HandleRoutedEvent")。
    猜你喜欢
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    相关资源
    最近更新 更多