任何人都可以在 WPF 中引发任何 RoutedEvent 吗?
在 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");
}
In C# events were always very protected: Only the owner of the event could trigger them. However, this seems to be completely different in WPF - Anyone can throw any event at any time. To test that, I've written the code in the bottom.
When I used RaiseEvent to raise Button.Click, the event above caught it. Is that the planned behavior of WPF events? Just letting anyone throw any events they wish? Also, if so, then what is the meaning of the OwnerType when you register the event? I thought it is some kind of protection, yet if it is, it is a poor one since anyone can access the public event and use AddOwner function to add more owners.
Thanks!
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>
Code behind
The custom control:
class VitalyControl : Label
{
public VitalyControl()
{
this.MouseDown += new MouseButtonEventHandler(VitalyControl_MouseDown);
}
void VitalyControl_MouseDown(object sender, MouseButtonEventArgs e)
{
RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
}
}
And the handler:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button was pressed");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是设计使然,实际上也是 RoutedEvents 的原因之一。它们被称为路由事件,因为它们是跨元素树路由的。您遇到的行为在 msdn 上称为“单一处理程序附加点” 。您指定 StackPanel 应侦听所有 Button.Click 事件。
在您的自定义控件中,您引发一个按钮单击事件。这个“冒泡”到处理它的堆栈面板。
更新:
为了使此路由正常工作,我假设每个UIElement都需要能够引发任何路由事件。路由事件仅由 UI 元素使用,是解决 WinForms 实现复杂性的答案。它们不能替代 CLR 事件。
所有者类型在内部使用按名称解析事件时< /a>.
This is by design, and is actually one of the reasons for RoutedEvents. They are called routed events because they are routed across the element tree. The behavior you are experiencing is called 'singular handler attachment point' on msdn. You specify that StackPanel should listen to all Button.Click events.
In your custom control, you raise a button click event. This 'bubbles' up to the stackpanel, which handles it.
UPDATE:
For this routing to work, I assume every UIElement needs to be able to raise any routed event. Routed Events are only used by UI elements, and are an answer to complexities with WinForms implementations. They aren't a replacement for CLR events.
The owner type is used internally when resolving an event by name.