我面临着下一个误解。
序言:
我有 wpf 应用程序,其中包含下一个基本 UI 部分:RadioButtons
以及一些基于Popup
(以组合框方式)使用下拉菜单的控件。根据一些逻辑每个单选按钮挂钩PreviewMouseDown
事件并做一些计算。在下一个场景中,
- 用户打开弹出窗口(不要选择任何东西,弹出窗口只是保持打开状态)
- 用户单击单选按钮
PreviewMouseDown
不会像预期的那样为单选按钮触发(因为Popup
feature)。
尽管有一个,我的目标仍然是射击PreviewMouseDown
。RadioButton
尝试解决:
快速而肮脏的解决方案是:如果需要,使用新源挂钩并重新触发事件,使用单选按钮作为PreviewMouseDown
源Popup
。PreviewMouseDown
新的来源可以通过MouseButtonEventArgs.MouseDevice.DirectlyOver
. Popup
下一段代码执行此操作(仅当“吃”PreviewMouseDown
外部点击时才会重新触发事件):
private static void GrantedPopupPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var popup = sender as Popup;
if(popup == null)
return;
var realSource = e.MouseDevice.DirectlyOver as FrameworkElement;
if(realSource == null || !realSource.IsLoaded)
return;
var parent = LayoutTreeHelper.GetParent<Popup>(realSource);
if(parent == null || !Equals(parent, popup ))
{
e.Handled = true;
var args = new MouseButtonEventArgs(e.MouseDevice,
e.Timestamp,
e.ChangedButton)
{
RoutedEvent = UIElement.PreviewMouseDownEvent,
Source = e.MouseDevice.DirectlyOver,
};
realSource.RaiseEvent(args);
}
}
当我将该处理程序直接附加到通过并且不工作(不会为单选按钮触发)时,如果我要附加一个通过(目的是避免将行为附加到使用这些单选按钮在页面上可能发生的每一个)上,这很有效:Popup.PreviewMouseDown
Behavior
PreviewMouseDown
EventManager.RegisterClassHandler
Popup
EventManager.RegisterClassHandler(
typeof (Popup),
PreviewMouseDownEvent,
new MouseButtonEventHandler(GrantedPopupPreviewMouseDown));
调试器显示e.MouseDevice.DirectlyOver
(参见上面的代码)是Popup
,而不是Radiobutton
(就像我通过 附加处理程序时那样Behavior
)!
问题:
如果事件处理程序以两种不同的方式附加,相同的操作如何以及为什么MouseButtonEventArgs
会有所不同?
有人可以解释这种行为吗?
非常感谢。