Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

ReactivePropertyでViewModelに紐づくModelを差し替えるときのパターン

$
0
0

という呟きを見つけたのでどういう風にやるのかをちょろっと。

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);
    }
}

Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>