15

いくつかの抽象ViewModel基本クラスで、次のような単純な古いプロパティがあるとしましょう。

public Size Size
{
    get { return _size; }
    set
    {
        _size = value;
        OnPropertyChanged("Size");
    }
}

次に、次のプロパティを含む前のViewModelを継承して、より具体的なViewModelを作成します。

public Rect Rectangle
{
    get { return new Rect(0, 0, _size.Width, _size.Height); }
}

ここで、一部のViewクラスで、前述のViewModelのRectangleプロパティにバインドします。サイズを変更するまで、すべて正常に動作します。Size変更された場合、Rectangleそれについては知らず、変更はビューに伝播されません。また、Rectangleは子クラスであるOnPropertyChanged("Rectangle")ため、Sizeセッターに単純にを追加することはできません。

ここで、のような多くの異なるプロパティがRectangleあり、それらはすべて基本クラスのプロパティに依存しており、これらの変更はいずれも伝播されていないことを想像してください。変更通知を連鎖させるための軽量でエレガントな方法が必要です。できれば、多くのコードを必要とせず、依存関係のプロパティを使用する必要がない方法が必要です。

明らかに、ここには醜い解決策がたくさんあります-私が探しているのは、クリーンで賢いものです。これは非常に一般的なシナリオであるように思われ、MVVMに適した方法があるように思われます。

4

5 に答える 5

9

私は最近、この正確な問題についてブログを書きました。[DependsUpon("Size")]Rectangleに属性を含めます。私はこのアプローチが本当に好きです。なぜなら、依存関係を作成するコードで依存関係の知識を保持し、その逆ではないからです。

ご覧ください: http: //houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx

于 2010-01-06T13:02:57.000 に答える
4

Josh SmithのPropertyObserverを使用します。これは、彼のMVVM Foundationライブラリ( http://mvvmfoundation.codeplex.com/)から入手できます。

使用法:

_viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel)
   .RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle);

ブライアンの属性アプローチも素晴らしいです。PropertyObserverについて私が気に入っていることの1つは、任意のコードを実行できることです。レイズを回避したり、他のアクションを一緒に実行したりする可能性のある条件を確認できます。

于 2010-01-06T16:48:09.167 に答える
3

次のように、派生ViewModelでOnPropertyChangedをオーバーライドするだけです。

protected override void OnPropertyChanged(string propertyName) {
    base.OnPropertyChanged(propertyName);
    if (propertyName == "Size") {
        base.OnPropertyChanged("Rectangle");
    }
}

別の可能性...しばらく前に、次のようなプロパティの属性をサポートする非常に優れたViewModel基本クラスをまとめました。

[DependsOn("Size")]
public Rect Rectangle {
    get { new Rect(0,0,Size.Width, Size.Height); }
}

次に、ViewModel基本クラスは実行時にこれらのDependsOnAttributeを収集し、そのOnPropertyChangedメソッドでは、基本的に、プロパティの変更が発生したときに無効にする必要がある他のプロパティを確認するだけです。

于 2010-01-06T00:27:56.110 に答える
1

クリーンなMVVMの方法は、Messengerサブスクライブ/通知メカニズムを使用することです(Josh SmithのMvvmFoundationのように)

どこかにシングルトンMessengerオブジェクトを作成します-メインのAppクラスは常にこれに適した場所です

public partial class App : Application
{
    private static Messenger _messenger;
    public static Messenger Messenger
    {
        get
        {
            if (_messenger == null)
            {
                _messenger = new Messenger();
            }
            return _messenger;
        }
    }
}

基本クラスのサイズセッターで、変更を通知します。

public Size Size
{
    get { return _size; }
    set
    {
        _size = value;
        OnPropertyChanged("Size");

        App.Messenger.NotifyColleagues("SIZE_CHANGED");
    }
}

これで、継承されたViewModelにこれらの変更をリッスンさせ、必要に応じてPropertyChangedイベントを発生させることができます...

public MyViewModel : MyViewModelBase
{
    public MyViewModel()
    {
        App.Messenger.Register("SIZE_CHANGED", () => OnPropertyChanged("Rectangle"));
    }
}

もちろん、このメッセージには必要な数のサブスクリプションを追加できます。変更をビューに通知する必要があるプロパティごとに1つ...

お役に立てれば :)

于 2010-01-06T00:28:32.200 に答える
0

おそらくVBの人であるためですが、Rectangleコードでは、ビューにアラートを出すためにOnPropertyChangedイベントを発生させないPublicSizeプロパティではなくprivate_size宣言にアクセスしているように見えます。

また、私はベースから外れているかもしれませんが、Sizeがそのオブジェクトのプロパティであるのに対し、Rectangleは実際のオブジェクトであるべきではありませんか?多分それはあなたがしていることです..いくつかのC#の方法論はまだ私にとって本当に異質です。

于 2010-01-06T12:42:34.997 に答える