はじめに
オレオレ解釈の覚え書き その10
変更通知プロパティの話から派生して、強力なライブラリである ReactiveProperty についてご紹介します。
本文
前回ご紹介した変更通知プロパティは、View 側のバインドは楽ですが、値の変更通知はそれぞれのプロパティが自ら行う必要がありました。値の変更に合わせて処理を切り替える場合は、ViewModel 内で PropertyChanged のイベントを捉えて、どのプロパティが変更されたのかを判断する必要があるため、複数のプロパティが関わるようになれば途端に管理が難しくなります。
変更通知や処理への橋渡しを ReactiveProperty は自動で行ってくれます。下記は ReactiveProperty による変更通知プロパティとそれを利用するコマンドの実装例です。[名前] にバインドされた "Name" が変更通知プロパティです。[ゲスト] ボタンは常に活性な "GuestCommand" に、[登録] ボタンは [名前] に値が設定されているときだけ活性化する "SubmitCommand" にバインドされています。ここでの「活性」「非活性」とはコマンドに紐づく処理(WithSubscribe 内の処理)が実行可能かどうかだけでなく、ボタンの Enabled の状態まで制御されます。
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Reactive.Disposables;
using System.Reactive.Linq;
namespace TestApp.ViewModels
{
public class MainWindowViewModel : IDisposable
{
private CompositeDisposable _disposable;
public ReactiveProperty<string> Name { get; }
public ReactiveCommand GuestCommand { get; }
public ReactiveCommand SubmitCommand { get; }
public MainWindowViewModel()
{
this._disposable = new CompositeDisposable();
this.Name = new ReactiveProperty<string>()
.AddTo(this._disposable);
this.GuestCommand = new ReactiveCommand()
.WithSubscribe(() => this.Name.Value = "Guest")
.AddTo(this._disposable);
this.SubmitCommand = this.Name
.IsEmpty()
.Inverse()
.ToReactiveCommand()
.WithSubscribe(() => this.ShowMessage(this.Name.Value))
.AddTo(this._disposable);
}
public void Dispose()
{
this._disposable.Dispose();
}
private void ShowMessage(string text)
{
// メッセージを表示する
}
}
}
<Window x:Class="TestApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:p="http://prismlibrary.com/"
p:ViewModelLocator.AutoWireViewModel="True">
<StackPanel>
<TextBox x:Name="名前" Text="{Binding Text.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button x:Name="ゲスト" Command="{Binding GuestCommand, Mode=OneTime}"/>
<Button x:Name="登録" Command="{Binding SubmitCommand, Mode=OneTime}"/>
</StackPanel>
</Window>
注意が必要な点として、ReqctiveProperty とバインドする場合、内包された値にアクセスするため ".Value" の記載が必要になります。(ReqctiveCommand は ICommand の実装であるためこの記載は不要です。)
おわりに
ReactiveProperty は neuecc さんが作成し、現在は okazuki さんによってメンテナンスされています。ライブラリの使い方はブログ等で大変分かりやすくまとめて頂いているため、より詳しい情報は是非開発者様のページをご覧ください。
・ReactiveProperty : Rx + MVVMへの試み
・MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー
・ReactiveProperty v7.0.0 をリリースしました
次回は依存関係プロパティについてまとめます。