2011-09-14 28 views
4

MVVMを初めて使用しようとしています。私はモデルクラス、ビューモデルクラス、ビューxamlページを持つWindows Phoneアプリ(マンゴー)を持っています。 VMにバインドされたコントロール(テキストボックス)があり、VMがモデルにバインドされています。MVVMがViewModelに通知していないINotifyPropertyChangedモデルの使用

モデルとビューモデルの両方がINotifyPropertyChangedを実装しています。私が使用している実装はコピーされているので、INPCで何をやっているのか分かりません。ここで両方のクラスに記載されているコードは:

public event PropertyChangedEventHandler PropertyChanged; 

private void NotifyPropertyChanged(String info) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 

Iのいずれか(テキストボックスからの)手動で設定するか、または(他の特性のいずれかを変更することによって)計算することができるモデルクラスの1つの特性を有しています。その結果を1つ呼んでみましょう。

PropertyChangednullであるにもかかわらず、変更されたプロパティと再計算されたプロパティの両方でINPCが呼び出され、コードの一部がスキップされます。その後、VMでは、変更されたプロパティがそのクラスのINPC(設定されたアクセサの一部として)をステップスルーし、今回はPropertyChangednullではないため、PropertyChangedメソッドが呼び出されます。ただし、Resultプロパティの場合、INPCは呼び出されません(そのプロパティには、他のプロパティのsetアクセサでINPCが呼び出されません)。ここ

は、算出されたプロパティされていない、モデルにおける特性の一つである:ここ

public int AgeSetting 
{ 
    get 
    { 
     return (int)GetValueOrDefault(AgeSettingKeyName, AgeSettingDefault); 
    } 
    set 
    { 
     AddOrUpdateValue(AgeSettingKeyName, value); 
     Calculate(); 
    } 
} 

はモデルで計算した値の特性です。ここのViewModelから

public int PointsSetting 
{ 
    get 
    { 
     return (int)GetValueOrDefault(PointsSettingKeyName, PointsSettingDefault); 
    } 
    set 
    { 
     AddOrUpdateValue(PointsSettingKeyName, value); 
    } 
} 

は、両方のプロパティは次のとおりです。

public int Age 
{ 
    get 
    { 
     return person.AgeSetting; 
    } 
    set 
    { 
     person.AgeSetting = value; 
     NotifyPropertyChanged("Age"); 
    } 
} 

public int PointsAllowed 
{ 
    get 
    { 
     return person.PointsSetting; 
    } 
    set 
    { 
     person.PointsSetting = value; 
     NotifyPropertyChanged("PointsAllowed"); 
    } 
} 

は、私がモデルクラスから、VMのクラスに、UIへのINPCべきバブルアップを期待していた、この前にやったことがないました。それはそのように働いているようには見えません。

Result(calculated)プロパティが変更されていることがわかりました。ページから離れて戻ってきて、新しく表示された値が正しいためです。私はちょうど、モデルの計算値、ビューモデル、そしてビューまでの取得方法を知らない。

ありがとうございます。

+0

便利なツールの1つがVSの出力ウィンドウです。これは、あなたのアプリケーションを起動してUIを初期化するときにバインディングが失敗したかどうかを示します。あなたの綴りが間違っているかもしれません。 –

+0

私はそれを知らなかった。ありがとうございました。しかし、バインディングは、隔離された配列セットに格納されている値をテキストボックスにプルするので、機能しています –

+0

私はあなたが本当に求めていることを理解する時間がありません。あなたのタイトル](http://stackoverflow.com/posts/7421606/edit)それはあなたが尋ねているものとの関係で実際の質問であるように?タグを有機的に使用するだけのボーナスポイント。ありがとう! – Will

答えて

5

計算されたプロパティの値が変更された場合は、そのプロパティのPropertyChangedイベントも発生させます。つまり、単一のプロパティーが変更された場合、複数のプロパティーに対してイベントが発生する可能性があります。

また、デザインで/スマートにできる場合は、モデルプロパティに直接バインドしてモデルをViewModelのプロパティにすることができます。この減少はコードのメンテナンスを多くします。

+0

+1。私は他のMVVM機能が必要でない限り、すでにINotifyPropertyChangedを実装しているクラスにViewModelを持っていることを知ることができません(つまり、既に完全にうまくバインドできるものを無意味に適応させます)。 – RichardOD

+0

ありがとうございます。はい、バス、私は複数のプロパティのために発射する必要があるかもしれない場所を見ることができます。私は何かがMで変わったときにそれが自動的だったと思った、VMはそれを見るだろう。また、はい、私はVからMにまっすぐに行くことができましたが、この練習のポイントはMVVMを学ぶことでした。私は前にそれをやっていないので、それを試してみたかった。しかし、マキシムがイベントハンドラとサブスクライブについて知っていることはわかっていますが、私のVMはMに「サブスクライブ」されていないので、プロパティを取得/設定します私はそれが私が見なければならないところだと思っています。 –

+1

一般的に、MVVMでは、Modelクラスはまったく通知しません。モデルは論理的であり、ビューモデルによってアクセス/変更されます。基本的には、View Modelで指示されていない限り、モデルは変更されません(MVCのModel/Controler序論に似ています)。例えば、ViewModelはモデルにデータベースからデータをロードするよう指示し、データロードが完了するとViewModelは通知します。 – EtherDragon

1

モデルでは、計算されたプロパティ呼び出しのNotterPropertyChangedメソッドのセッターにあります。あなたのアプリのいくつかのロジックは、モデルを更新する必要があります。 ViewModelがこのイベントに登録されていることを確認してください。これは非常に重要です。なぜなら、これはあなたがここで欠けているものだと思うからです。

次に、PropertyChangedイベントのモデルに登録されているViewModelのEventHandlerで、ViewModelの適​​切なプロパティ値を変更します(ビューモデルのここのメソッドはビューモデルのプロパティを更新します)。に縛られている。

+0

私のモデルでは、プロパティが変更されるたびにNPCメソッドが呼び出されますが、setterにはありませんが、setter(isostoreに値を保存するメソッド)から呼び出される別のメソッドで呼び出されます。私はステップを踏んで、そのメソッドが呼び出されます。しかし、私が欠けているかもしれないものは、あなたが話すイベントハンドラです。私はあなたが "モデルのPropertyChanged"イベントを購読することによって何を意味するのかよくわからないので、そのことを検討します。そのままでは、私のVMプロパティはモデルのインスタンスからちょうど引っ張り出します。それが鍵かもしれない。私はそれを調べます。ありがとう! –

+0

たとえば、モデルにPropertyChangedというパブリックイベントがある場合、このイベントにサブスクライブするビューモデルには、A)モデルB)への参照が必要です。同様にmodel.PropertyChanged + = OnModelChanged; OnModelChangedでは、UIがバインドされているパブリックプロパティの値を設定します。この方法で、通知リンクが完了します。 –

3

他のプロパティの値に依存するプロパティの場合、プログラマは複数のプロパティが変更されたことを通知する必要があります。

の3つのプロパティを持つクラスを考える - スコア、乗算器、および合計 - 合計スコアと乗数の値に依存している、私はクラスそうのように書くことができます。

public class ViewModel 
{ 
    private int score; 
    public int Score 
    { 
     get 
     { 
      return this.score; 
     } 
     set 
     { 
      if (this.score != value) 
      { 
       this.score = value; 
       // Notify that this property has changed 
       NotifyOfPropertyChange(() => this.Score); 
       // Notify that a dependant property has changed 
       NotifyOfPropertyChange(() => this.Total); 
      } 
     } 
    } 

    private int multiplier; 
    public int Multiplier 
    { 
     get 
     { 
      return this.multiplier; 
     } 
     set 
     { 
      if (this.multiplier != value) 
      { 
       this.multiplier = value; 
       // Notify that this property has changed 
       NotifyOfPropertyChange(() => this.Multiplier); 
       // Notify that a dependant property has changed 
       NotifyOfPropertyChange(() => this.Total); 
      } 
     } 
    } 

    public int Total 
    { 
     get 
     { 
      return this.Score * this.Multiplier; 
     } 
    } 
} 
あなたが気づく

、用Scoreの値を設定すると、ScoreとTotalの両方が変更されたことが通知されます。あなたの具体的なNotifyOfPropertyChangeの実装は、私の見た目と違って見えますが、中心的なアイデアは同じです。合計は他のプロパティの値に依存するプロパティなので、決して通知しません。代わりに、Totalが依存している部分は通知する責任があります。

1

モデルクラスでINotifyPropertyChangedインターフェイスを実装していないようですね。これがなければ、イベントハンドラは呼び出されるとnullになります。

public class ViewModel : INotifyPropertyChanged 
{ 
    // Stuff 
} 

public class Model : INotifyPropertyChanged 
{ 
    // Stuff 
} 

また、私のブログでは、いくつかのMVVMに関する記事をチェックしています。私は、文字列値を使用せずに(代わりにリフレクションを使用して)Inotifyを起動するいくつかのチュートリアルだけでなく、いくつかの方法を持っています。

+0

私はあなたのブログ記事を見ました。私はまだそれを実装しようとしていないが、私はそれを信じている。変更されたプロパティの名前を取得するためにリフレクションを使用する方法が好きです。しかし、この場合は、このビューのモデルビューを削除することが最善の方法であると判断しました。私はそれを見ました。この場合、モデルビューはモデルをビューに渡すだけです。ヒントをありがとう。 –

関連する問題