2016-11-18 2 views
1

ビューモデル(未指定型)のfooという名前のプロパティの変更に対応する最善の方法は、ビューモデルINotifyPropertyChangedを正しく実装していますか?コード内のビューモデルプロパティの変更に対処する

通常、モデル要素を表示するためにコントロール要素をバインドすることができ、すべてが機能します。しかし、この場合、これでは不十分で、プロパティが変更されたときにC#のいくつかの行を実行する必要があります。

DataContextの対応するイベントをリッスンできますが、DataContext自体の変更も処理できます。もう1つの解決策は、DependencyPropertyをコードビハインドファイルに導入することです。しかし、そこに短い方法はありませんか?

+0

私は質問を正しく理解していませんが、ViewModelで直接バインドされたプロパティの変更に反応しないのはなぜですか? – Fang

+0

良い質問ですが、質問にこれを言及する必要があります。その理由は、(特定のコントロールに列を追加することによって)コントロールを直接変更する必要があるためです。私はビューモデルでそれをしたくありません。 – MarkusParker

+0

プロパティFooには何が結びついていますか? – adminSoftDK

答えて

3

可能であれば、これを避けることをおすすめします。必要な場合は、PropertyChangedイベントを購読してください。

私はこのコードをコードビハインドコンストラクタに配置します。

INotifyPropertyChanged viewModel = (INotifyPropertyChanged)this.DataContext; 
viewModel.PropertyChanged += (sender, args) => { 
    if (!args.PropertyName.Equals("foo")) 
     return; 
    // execute code here. 
}; 

保守性の先端あなたはデータコンテキストが、その型にキャスト、プロパティを持っているタイプであることを確実に知るとnameofオペレータではなく、魔法の文字列を使用している場合。

編集(DataContextの変化に反応)

あなたはデータコンテキストの変更を処理するためにDataContextChangedイベントをサブスクライブすることができるはずです。

INotifyPropertyChanged previous; 
// constructor 
public SomeCodeBehindClass() 
{ 
    previous = (INotifyPropertyChanged)this.DataContext; 
    DataContextChanged += (sender, args) => SubscribeToFooChanges((INotifyPropertyChanged)args.NewValue); 
    SubscribeToFooChanges(previous); 
} 

// subscriber 
private void SubscribeToFooChanges(INotifyPropertyChanged viewModel) 
{ 
    if (previous != null) 
     previous.PropertyChanged -= FooChanged; 
    previous = viewModel; 
    if (viewModel != null) 
     viewModel.PropertyChanged += FooChanged; 
} 

// event handler 
private void FooChanged (object sender, PropertyChangedEventArgs args) 
{ 
    if (!args.PropertyName.Equals("foo")) 
     return; 
    // execute code here. 
} 
+1

これは有効な解決策ですが、上記のように、 'this.DataContext'が変更されたときに余分な作業をしなければなりません。 xamlでバインディングを使用する場合、これは必須ではありません。私はそれが後ろにあるコードで同様のことをすることが可能かどうか疑問に思います。 – MarkusParker

+0

DataContextChanged DependencyPropertyChangedEventHandlerを使用した例を追加しました。私はコードを実行していない。 –

+1

SubscribeToFooChangesメソッドの 'previous'と' viewModel'のヌルチェックを行う必要があります。これは、DataContextがnullから始まり、nullにも代入できるためです。 –

-1

これらのコード行は、ビジネスロジックに関連する場合、コードの背後で使用しないでください。このプロパティの値は何とかあなたが

1

に考えられる解決策をコンバータを使用する必要があります前処理されなければならない場合は、他の例では、ビューモデルのプロパティはいつもあなたの後ろにあなたのコードでは、任意のマークアップ要素にバインドされます この

を行うことができます
(((dynamic)DataContext).foo as ObservableCollection<object>).CollectionChanged += (s, e) => 
     { 
      if (e.Action == NotifyCollectionChangedAction.Replace) 
      { 

      } 
      else 
      { 
       //and so on 
      } 
     }; 
+0

これは興味深いアプローチですが、DataContextが変更されるか変数fooに別の値が割り当てられるかは考慮されません。 – MarkusParker

+0

@ MarkusParker DataContextChangedは、コードの背後にあるeaslyにアクセスできるイベントです。コレクション全体を新しい値に割り当てることは良い考えではありません。すべてのバインディングを再割り当てする必要があるからです(http://updatecontrols.net/doc/tips/common_mistakes_observablecollectionを参照してください)。コレクションをクリアする方が良いです。 – adminSoftDK

関連する問題