3

在 C# 中,事件总是受到非常严格的保护:只有事件的所有者才能触发它们。但是,这在 WPF 中似乎完全不同——任何人都可以随时抛出任何事件。为了测试这一点,我在底部编写了代码。

当我使用 RaiseEvent 来引发 Button.Click 时,上面的事件捕获了它。这是 WPF 事件的计划行为吗?只是让任何人抛出他们想要的任何事件?另外,如果是这样,那么注册事件时 OwnerType 的含义是什么?我认为这是某种保护,但如果是这样,那就太糟糕了,因为任何人都可以访问公共事件并使用 AddOwner 函数添加更多所有者。

谢谢!

XAML

<StackPanel Button.Click="ButtonBase_OnClick">
    <Button Name="RealButton">Real button</Button>
    <WpfWindow:VitalyControl MouseDown="UIElement_OnMouseDown">
      I am almost a button
    </WpfWindow:VitalyControl>
</StackPanel>

背后的代码

自定义控件:

class VitalyControl : Label
{
    public VitalyControl()
    {
        this.MouseDown += new MouseButtonEventHandler(VitalyControl_MouseDown);
    }

    void VitalyControl_MouseDown(object sender, MouseButtonEventArgs e)
    {
        RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
    }
}

和处理程序:

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Button was pressed");
    }
4

1 回答 1

3

这是设计使然,实际上是 RoutedEvents 的原因之一。它们被称为路由事件,因为它们是跨元素树路由的。您遇到的行为在msdn上称为“单一处理程序附加点” 。您指定 StackPanel 应侦听所有 Button.Click 事件。

在您的自定义控件中,您会引发一个按钮单击事件。这会“冒泡”到处理它的堆栈面板。

更新:

为了让这个路由工作,我假设每个UIElement都需要能够引发任何路由事件。路由事件仅由 UI 元素使用,是对 WinForms 实现复杂性的一种解决方案。它们不能替代 CLR 事件。当按名称解析事件时,所有者类型在内部使用。

于 2011-02-03T18:09:27.923 回答