我正在编写一个WPF行为,该行为应该阻止当鼠标不在特定方块内时发生的所有鼠标事件。我希望行为附加一个PreviewMouse ***事件处理程序,它检查鼠标位置,如果鼠标不在特定方格内,则设置Handled = true。问题是有很多不同的鼠标事件,我更喜欢我的代码优雅和干净。有没有办法在一条优雅的线条中捕捉所有预览鼠标事件? Thnx,
答案 0 :(得分:3)
您可以使用反射附加到名称中包含“PreviewMouse”的所有事件。要实现这一点,您只需为UIElement创建一个扩展方法,并像这样实现它
public static class UIElementExtensions
{
public static void HandleAllPreviewMouse(this UIElement uiElement, RoutedEventHandler handler)
{
var elementType = uiElement.GetType();
foreach (var eventInfo in elementType.GetEvents().Where(ei => ei.Name.Contains("PreviewMouse")))
{
var specificHandler = Delegate.CreateDelegate(eventInfo.EventHandlerType, handler.Method);
eventInfo.AddEventHandler(uiElement, specificHandler);
}
}
}
然后在你的Window代码后面使用扩展名将你的处理代码附加到你的根布局网格(或你要挂钩的whavetever父元素)
public MainWindow()
{
InitializeComponent();
var handler = new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
Console.WriteLine("Preview event fired");
// Uncomment if you want to block event propagation
//e.Handled = true;
});
this.LayoutRoot.HandleAllPreviewMouse(handler);
}
此解决方案是针对您的问题的单线解决方案,但请记住,它不是特别干净,尤其是在根据其名称过滤事件的部分。但是你可以肯定地做一些工作来使它变得更好。
答案 1 :(得分:2)
PreviewMouse 事件是隧道事件,因此它们从根元素隧道传输到实际的发件人。因此,如果您不想明确附加到所有子元素,则可以将PreviewMouse*** event handler
挂钩到根元素上。
在处理程序中,您可以检查e.OriginalSource
以获得实际引发该事件的控件,并可以进行相应的编码。
<Grid PreviewMouseLeftButtonDown="Handler">
<Button/>
<TextBox/>
<TextBlock/>
<AnotherControl/>
</Grid>
评论更新:
我正在寻找的是一个附加一个C#代码的代码 单个事件处理程序,对同一个许多不同的鼠标事件 元素(PreviewMouseDown,PreviewMouseUp,PreviewLeftMouseDown, PreviewLeftMouseUp,PreviewMouseWheel ...)。而不是附加 具体到每个事件的相同处理程序,我想将其附加到 所有这些都是一次性的。
我认为你在这里复杂化只是为了避免一些代码行。这些事件彼此独立,因此您必须以一种或另一种方式为其分配处理程序(可能与其他答案中提出的反射一样)。但是,考虑到反射速度慢,我认为这不是一个很好的方法。而且,通过这种方法,您将获得相同的代码行。
如果需要关注代码行,那么您可以封装在一个方法中并将公共处理程序传递给它并将处理程序挂钩到感兴趣的事件。
private void HookPreviewMouseEvents(MouseButtonEventHandler handler)
{
PreviewMouseDown += handler;
PreviewMouseLeftButtonUp += handler;
PreviewMouseUp += handler;
}