[英]Reactive extensions and MouseEventArgs source
I am using RX in my WPF applications to track mouse movement. 我在WPF应用程序中使用RX来跟踪鼠标移动。
When subscribing directly to the mouse move event I get a different source in my MouseEventArgs compared to when I use the sample method of RX. 直接订阅鼠标移动事件时,与使用RX的示例方法相比,我在MouseEventArgs中获得了不同的源。
For the sake of explanation here is a simple example: 为了便于解释,这里有一个简单的例子:
I have a window containing a grid and a button: 我有一个包含网格和按钮的窗口:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="grid">
<Button></Button>
</Grid>
</Window>
I subscribe to the mouse move event with RX: 我订阅了RX的鼠标移动事件:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Observable.FromEventPattern<MouseEventArgs>(grid, "MouseMove").Subscribe(mouseMoveRx);
Observable.FromEventPattern<MouseEventArgs>(grid, "MouseMove").Sample(TimeSpan.FromSeconds(1)).Subscribe(mouseMoveRxSample);
}
private void mouseMoveRx(System.Reactive.EventPattern<MouseEventArgs> obj)
{
var element = obj.EventArgs.Source as UIElement;
//element is System.Windows.Controls.Button
}
private void mouseMoveRxSample(System.Reactive.EventPattern<MouseEventArgs> obj)
{
var element = obj.EventArgs.Source as UIElement;
//element is Microsoft.Windows.Themes.ButtonChrome
}
The first handler is having System.Windows.Controls.Button
as source whereas the second handler is having Microsoft.Windows.Themes.ButtonChrome
as source. 第一个处理程序将
System.Windows.Controls.Button
作为源,而第二个处理程序将Microsoft.Windows.Themes.ButtonChrome
作为源。
What is the reason for the different source? 不同来源的原因是什么?
I have no experience with WPF so take this answer with a grain of salt... 我没有WPF的经验,所以请耐心等待这个答案......
But, based on your experiment with Do
, it appears that what is happening is that after the event fires and Sample
caches the value, the event object is mutated presumably by WPF. 但是,根据你对
Do
的实验,看来发生的事情是在事件触发和Sample
缓存值之后,事件对象可能是由WPF变异的。
The Remarks
section of MouseEventArgs documentation says this: MouseEventArgs文档的
Remarks
部分Remarks
了这一点:
The attached events and the base element routed events share their event data, and the bubbling and tunneling versions of the routed events also share event data.
附加事件和基本元素路由事件共享其事件数据,路由事件的冒泡和隧道版本也共享事件数据。 This can affect the handled characteristics of the event as it travels the event route.
这会影响事件在事件路径中传播时的处理特征。 For details, see Input Overview.
有关详细信息,请参阅输入概述
This seems to suggest that indeed WPF mutates the event object as it bubbles it up the element hierarchy. 这似乎表明,事实上,WPF会将事件对象变为元素层次结构。 Any settable property on the object is subject to this behavior.
对象上的任何可设置属性都受此行为的影响。 In this case it appears that
Source
is the only thing you need to worry about. 在这种情况下,看起来
Source
是您唯一需要担心的事情。
To handle this, you effectively need to cache the Source
value before you apply any Rx operator that introduces asynchronicity because you can only trust the Source
property for as long as your WPF event handler is running. 要处理这个问题,在应用引入异步性的任何Rx运算符之前,实际上需要缓存
Source
值,因为只要WPF事件处理程序正在运行,您就只能信任Source
属性。 The simplest way is to use a Select
clause to capture Source
: 最简单的方法是使用
Select
子句捕获Source
:
Observable.FromEventPattern<MouseEventArgs>(grid, "MouseMove")
.Select(e => Tuple.Create(e.EventArgs.Source as UIElement, e.EventArgs))
.Sample(TimeSpan.FromSeconds(1))
.Subscribe(mouseMoveRxSample);
// ...
private void mouseMoveRxSample(Tuple<UIElement, MouseEventArgs> obj)
{
var element = obj.Item1;
//element is System.Windows.Controls.Button
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.