LoginSignup
10
6

More than 5 years have passed since last update.

ReactiveProperty同士で双方向バインディングする

Posted at

はじめに

ReactiveProperty同士で双方向バインディングしたい状況があり、その方法について調査したのですが記述している情報がネット上でないっぽいので紹介がてら投稿します。

状況

a.png
こんな感じでViewModelではプリミティブっぽい型で入力を受けて、正しい情報はModelで保持。その際にはDDD的なValueObjectに変換済みにしておきたい状況です。
ちなみにModelがINotifyPropertyChangedを継承している場合のToReactivePropertyAsSynchronizedを使用した双方向バインディングの例は多数ありました。

Inputに入力するべき初期値がViewModelのコンストラクタ時点で入手可能ならばViewModel -> ModelのOneWay的なバインディングでも良かったんですが、今回の状況としては初期値は非同期処理の後で手に入るため、Model -> ViewModelのOneWayToSource的なバインディングもしたかったです。

サンプルとライブラリ

実装例

実際に動作するソースはReactivePropertySample(自作)を参照。

Model
    public class Model
    {
        public ReactivePropertySlim<ValueObject> VO { get; } = new ReactivePropertySlim<ValueObject>();

        public async void 非同期処理Async()
        {
            var ret = await なんか非同期処理();
            VO.Value = new ValueObject(ret.非同期処理で手に入れた初期値);
        }
    }
ViewModel
    public class ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private CompositeDisposable DisposeCollection = new CompositeDisposable();
        public ReactiveProperty<string> Input { get; }
        public Model Model { get; }

        public ViewModel(Model _model)
        {
                Model = _model;
                Input =
                    Model.VO.ToReactivePropertyAsSynchronized(
                        x => x.Value, // propertySelector.
                        x => x.Name/* ValueObject型のstirngプロパティ */,  // convert.
                        x => new ValueObject(x), // convertBack.
                        ReactivePropertyMode.Default | ReactivePropertyMode.IgnoreInitialValidationError, // mode.
                        true // ignoreValidationErrorValue.
                    ).SetValidateNotifyError(x => String.IsNullOrEmpty(x) ? "何か入力してください。" : null) // バリデーション.
                    .AddTo(DisposeCollection);
        }

        public void OnNavigatedTo(NavigationContext navigationContext) => Model.非同期処理Async();
    }

解説

結局ToReactivePropertyAsSynchronizedを使用して実現するんですけど。
言いたいことはToReactivePropertyAsSynchronizedINotifyPropertyChangedを型パラメーターの制約に指定しているのでINotifyPropertyChangedを継承しているReactiveProperty(Slim)でも使用できますよってことです。

まとめ

メソッドの使い方の一例として誰かの参考になればと思います。

10
6
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
10
6