んー?
変更通知プロパティのメンバを持つModelで、そのメンバがViewModelのReactivePropertyに接続されてて、そのModelのインスタンス自体を差し替えたい時ってどうすればいいんだ・・・?
— たき(=゚ω゚)ノ (@taky_xi2) 2015, 6月 20
という呟きを見つけたのでどういう風にやるのかをちょろっと。
Modelのプロパティの変更を監視してViewModelを作り直す
こんなPersonクラスがあるとします。
publicclass Person : INotifyPropertyChanged { publicevent PropertyChangedEventHandler PropertyChanged; privatestaticreadonly PropertyChangedEventArgs NamePropertyChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); privatestring name; publicstring Name { get { returnthis.name; } set { if (this.name == value) { return; } this.name = value; this.PropertyChanged?.Invoke(this, NamePropertyChangedEventArgs); } } }
そして、それを保持するAppModelとかいうクラスがいるとします。
publicclass AppModel : INotifyPropertyChanged { publicevent PropertyChangedEventHandler PropertyChanged; privatestaticreadonly PropertyChangedEventArgs PersonPropertyChangedEventArgs = new PropertyChangedEventArgs(nameof(Person)); private Person person; public Person Person { get { returnthis.person; } set { if (this.person == value) { return; } this.person = value; this.PropertyChanged?.Invoke(this, PersonPropertyChangedEventArgs); } } publicvoid ChangePerson() { this.Person = new Person(); } }
ChangePersonでPersonクラスのインスタンスを差し替えるっていうイメージ。
んで、Personに紐づくVM。
publicclass PersonViewModel : IDisposable { public ReactiveProperty<string> Name { get; private set; } public PersonViewModel(Person model) { this.Name = model.ToReactivePropertyAsSynchronized(x => x.Name); } publicvoid Dispose() { this.Name.Dispose(); } }
そして、PersonViewModelを持ってるMainPageViewModelがこんな感じ。AppModelのPersonの変更を監視して、PersonViewModelを作り直しています。
publicclass MainPageViewModel { private AppModel model = new AppModel(); public ReadOnlyReactiveProperty<PersonViewModel> Person { get; private set; } public MainPageViewModel() { this.Person = model .ObserveProperty(x => x.Person) .Do(_ => this.Person?.Dispose()) .Select(x => new PersonViewModel(x)) .ToReadOnlyReactiveProperty(); } }
PersonViewModelを作り直したくない
そんな時は、悲しいけどPersonViewModelにINotifyPropertyChangedを実装して、ReactiveProperty型のプロパティの変更通知を実装しておきます。そうするとこんな感じでModelの差し替えができます。
publicclass PersonViewModel : INotifyPropertyChanged { publicevent PropertyChangedEventHandler PropertyChanged; privatestaticreadonly PropertyChangedEventArgs NamePropertyChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); private ReactiveProperty<string> name; public ReactiveProperty<string> Name { get { returnthis.name; } set { if (this.name == value) { return; } this.name?.Dispose(); // 直前のModelとの接続を切断this.name = value; this.PropertyChanged?.Invoke(this, NamePropertyChangedEventArgs); } } publicvoid SetModel(Person p) { this.Name = p.ToReactivePropertyAsSynchronized(x => x.Name); } }