我在我的 WPF 应用程序中使用 RX 来跟踪鼠标移动。
与使用 RX 示例方法时相比,当直接订阅鼠标移动事件时,我在 MouseEventArgs 中获得了不同的来源。
为了便于说明,这里有一个简单的例子:
我有一个包含网格和按钮的窗口:
<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>
我用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
}
第一个处理程序将 System.Windows.Controls.Button
作为源,而第二个处理程序将 Microsoft.Windows.Themes.ButtonChrome
作为源。
不同来源的原因是什么?
最佳答案
我没有使用 WPF 的经验,所以对这个答案持保留态度......
但是,根据您对 Do
的实验,似乎正在发生的事情是在事件触发并且 Sample
缓存值之后,事件对象大概发生了变化通过 WPF。
MouseEventArgs documentation 的备注
部分是这样说的:
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.
这似乎表明,WPF 在元素层次结构中向上冒泡时确实改变了事件对象。对象上的任何可设置属性都受此行为影响。在这种情况下,Source
似乎是您唯一需要担心的事情。
要处理这个问题,您实际上需要在应用任何引入异步性的 Rx 运算符之前缓存 Source
值,因为您只能信任 Source
属性您的 WPF 事件处理程序正在运行。最简单的方法是使用 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
}
关于c# - 响应式扩展和 MouseEventArgs 源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25730095/