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