コードビハインドで処理するイベントをストリームとして扱うサンプルプログラムです。
マウス座標を取得しタイトルバーに表示するアプリケーションになります。
ソースコード
ファイル名:RxMouseMove.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Reactive" Version="6.0.0" />
<PackageReference Include="System.Reactive.PlatformServices" Version="6.0.0" />
</ItemGroup>
</Project>
ファイル名:MainWindow.xaml.cs
using System.Windows;
using System.Windows.Input;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Threading;
namespace RxMouseMove;
public partial class MainWindow : Window
{
private IDisposable? _subscription;
public MainWindow()
{
InitializeComponent();
// Windowがロードされたら購読開始
Loaded += (_, __) =>
{
var context = SynchronizationContext.Current!;
var uiScheduler = new SynchronizationContextScheduler(context);
SetupMouseRx(uiScheduler);
};
// 閉じるときにはDispose
Closed += (_, __) => _subscription?.Dispose();
}
private void SetupMouseRx(IScheduler uiScheduler)
{
// マウス移動イベントをObservable化
var mouseMove = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(
h => this.MouseMove += h,
h => this.MouseMove -= h
);
// 座標のストリームを作成
_subscription = mouseMove
.Select(ev => ev.EventArgs.GetPosition(this)) // Pointを取り出す
.Throttle(TimeSpan.FromMilliseconds(5)) // 負荷軽減(任意)
.ObserveOn(uiScheduler) // UIスレッドへ戻す
.Subscribe(p =>
{
Title = $"X={p.X:F0} Y={p.Y:F0}";
});
}
}
実行イメージ
ウィンドウ内でマウスカーソルを移動させると、タイトルバーに座標が表示されます。
感想
今一つ理解が足りていないのですが、mouseMoveをSubscribeしていることは確認できます。
まず、イベントをObservaleへ変換
// マウス移動イベントをObservable化
var mouseMove = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(
h => this.MouseMove += h,
h => this.MouseMove -= h
);
次に、Observale化したストリーム(mouseMove)を購読(Subscribe)する条件をメソッドチェーンで定義しています。
// 座標のストリームを作成
_subscription = mouseMove
.Select(ev => ev.EventArgs.GetPosition(this)) // Pointを取り出す
.Throttle(TimeSpan.FromMilliseconds(5)) // 負荷軽減(任意)
.ObserveOn(uiScheduler) // UIスレッドへ戻す
.Subscribe(p =>
{
Title = $"X={p.X:F0} Y={p.Y:F0}";
});
マウス座標を取得するだけなら、イベント処理を書いた方がシンプルですが、負荷軽減で間引くコードなどはイベント処理では意外と面倒です。理解が進んだらもう少し複雑な処理を書いてみたいと思います。

コメント