Rx環境の構築とRxイロハのイ

Rxって何かって理論的な話はネットに先人たちの軌跡と解説がいろいろあるんでそっちを参照してくれたらいいと思う。
どう考えたって俺っちの場末のブログより先人たちの軌跡の方が検索結果上位にくるやろからね。

俺っちは自分がやったとおりを公開して同じ道をくる人に優しい情報を残したい。
まずはRxをNuGetからインストールする手順から。

1.RxDragDropというWPFアプリケーションを作る
2.ソリューションエクスプローラからNuGet起動(?)
3.Rxライブラリのインストール

こんだけ。
1.RxDragDropというWPFアプリケーションを作る

※詳細は省略

2.ソリューションエクスプローラからNuGet起動(?)
ソリューションエクスプローラのプロジェクトの上右クリックしてポップアップメニュー起動

「NuGetパッケージの管理」を選ぶ

次に飛び出してくるダイアログで「オンライン」で「Rx」を検索する。

で、MainLibraryってのをインストールする。

途中でライセンスを確認されるんで、当然のごとくYes!Yes!Yes!

で、インストールが完了する。


ここまですんなりイケたんで、あとは習うよりなれよの精神でネットからサンプルコードを拾ってきて動かしながら理解しようって
軽く思ってたのな。思ってたのな。思ってたのな。
いくつかネットでRxを使ったマウスイベントの合成の例が見つかった中で比較的日付の新しいかずき(id:okazuki)さんのサンプルをいただくことにした。

Reactive Extensions再入門 その9「Skip + Take + Repeat = ドラッグ」
http://okazuki.hatenablog.com/entry/20111124/1322145011

解説内容の理解もそこそこに(慣れるのが目的なので、実行結果を観察して推測する)コードの断片を繋ぎあわせて
アプリケーションに取り込む。

MainWindow.xaml

<Window x:Class="RxDragDrop.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;

namespace RxDragDrop
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // マウスダウン、マウスアップ、マウスムーブのIObservableを作る
            var mouseDown = Observable.FromEvent<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => (s, e) => h(e),
                h => this.MouseDown += h,
                h => this.MouseDown -= h);

            var mouseMove = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
                h => (s, e) => h(e),
                h => this.MouseMove += h,
                h => this.MouseMove -= h);

            var mouseUp = Observable.FromEvent<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => (s, e) => h(e),
                h => this.MouseUp += h,
                h => this.MouseUp -= h);

            var drag = mouseMove
                // マウスムーブをマウスダウンまでスキップ。マウスダウン時にマウスをキャプチャ
                .SkipUntil(mouseDown.Do(_ => this.CaptureMouse()))
                // マウスアップが行われるまでTake。マウスアップでマウスのキャプチャをリリース
                .TakeUntil(mouseUp.Do(_ => this.ReleaseMouseCapture()))
                // ドラッグが終了したタイミングでCompletedを表示
                .Finally(() => textBlock.Text = "Completed")
                // これを繰り返す
                .Repeat();

            // ドラッグ中は、イベント引数から座標を取り出して表示用に整えてTextBlockに設定
            drag.Select(e => e.GetPosition(null))
                .Select(p => string.Format("X: {0}, Y:{1}", p.X, p.Y))
                .Subscribe(s => textBlock.Text = s);
        }
    }
}

・・・ね?黒魔術でしょ?(苦笑)
コードの端々が何やってるかは後からついてくるとして、このコードでマウスダウン、アップまでの間のマウス座標を表示、マウスアップで"Completed"って表示に切り替わる。

このコードをきちんと理解しようと思ったら、色んな断面での型(変数、引数)とラムダ式LINQの知識ぐらいは最低でも必要になる。
もちろんRxの知識は当然なんやけど、それはこれからとして。

Rxのコアな動作に集中出来るように、コードを分解して大事なとこだけ取り出す。

using System;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;

namespace RxDragDrop
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var mouseMove = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
                h => (s, e) => h(e),
                h => this.MouseMove += h,
                h => this.MouseMove -= h);

            mouseMove.Subscribe(arg => Console.WriteLine(arg.GetPosition(null)));
        }
    }
}

こんだけ。シンプルっしょ?

長くなってきたんで続く。