6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ViewModel と変更通知プロパティ(ReactiveProperty)

Last updated at Posted at 2020-06-16

はじめに

オレオレ解釈の覚え書き その10

変更通知プロパティの話から派生して、強力なライブラリである ReactiveProperty についてご紹介します。

本文

前回ご紹介した変更通知プロパティは、View 側のバインドは楽ですが、値の変更通知はそれぞれのプロパティが自ら行う必要がありました。値の変更に合わせて処理を切り替える場合は、ViewModel 内で PropertyChanged のイベントを捉えて、どのプロパティが変更されたのかを判断する必要があるため、複数のプロパティが関わるようになれば途端に管理が難しくなります。

変更通知や処理への橋渡しを ReactiveProperty は自動で行ってくれます。下記は ReactiveProperty による変更通知プロパティとそれを利用するコマンドの実装例です。[名前] にバインドされた "Name" が変更通知プロパティです。[ゲスト] ボタンは常に活性な "GuestCommand" に、[登録] ボタンは [名前] に値が設定されているときだけ活性化する "SubmitCommand" にバインドされています。ここでの「活性」「非活性」とはコマンドに紐づく処理(WithSubscribe 内の処理)が実行可能かどうかだけでなく、ボタンの Enabled の状態まで制御されます。

ViewModel
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)
        {
            // メッセージを表示する
        }
    }
}
View
<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 をリリースしました

次回は依存関係プロパティについてまとめます。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?