2014-09-08 3 views
3

Я использую RX в своих приложениях WPF для отслеживания движения мыши.Реактивные расширения и источник MouseEventArgs

При подписке на событие перемещения мыши я получаю другой источник в MouseEventArgs по сравнению с тем, когда я использую метод образца RX.

Для удобства объяснения здесь простой пример:

У меня есть окно, содержащее сетку и кнопки:

<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 в качестве источника.

В чем причина разного источника?

+0

Является ли это поведение соответствует? Или вы только что это видели? Это то, что вы только что нажали на кнопку на границе кнопки? Вы, в конце концов, подписываетесь на событие «MouseMove» на «Grid», поэтому все, что угодно в «Grid», которое занимает пиксель экрана, потенциально может быть источником события. –

+0

Это последовательное поведение. Он также не изменяется, если я использую SourceSource вместо источника. – Postlagerkarte

+0

Что делает. Пример (TimeSpan.FromSeconds (1))? –

ответ

0

У меня нет опыта работы с WPF так взять этот ответ с зерном соли ...

Но, основываясь на своем опыте с Do, оказывается, что то, что происходит в том, что после пожаров событий и Sample кэшей значение, объект события мутируется предположительно WPF.

Remarks часть MouseEventArgs documentation говорит это:

Прикрепленные события и базовый элемент перенаправленные события обмениваться данными о событиях , а бурлит и туннельные версии разгромленных событий также обмениваться данными о событиях. Это может повлиять на характеристики обработанных событий при прохождении маршрута события. Для деталей см. «Обзор ввода».

Это, по-видимому, говорит о том, что действительно WPF мутирует объект события, поскольку он выравнивает его по иерархии элементов. Любое устанавливаемое свойство объекта зависит от этого поведения. В этом случае кажется, что Source - единственное, о чем вам нужно беспокоиться.

Для этого вам необходимо кэшировать значение Source, прежде чем применять какой-либо оператор Rx, который вводит асинхронность, поскольку вы можете доверять только объекту 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 
} 
Смежные вопросы