2016-12-27 10 views
0

私はかなり初心者です。モデルのデータが変更され、ビューモデルに通知する必要があり、ビューはビューモデル内のプロパティと物に似ています。これは正しいです?もしそうなら、私はモデルがINotifyPropertyChangedを実装し、このモデルからViewModelのプロパティを正しく更新する方法

public class LoginModel : INotifyPropertyChanged 
{ 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void NotifyPropertyChanged(string propName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); 
    } 

    public bool Authenticated { get; set; } 
} 

と私のViewModelのようになりますことを読んでいる、私は、プロパティを持っている「AuthResult」、それが「モデルプロパティからアップデートを取得する必要があります

public partial class view1 : UserControl, INotifyPropertyChanged{ 
public bool AuthResult 
    { 
     get 
     { 
      return _authVal; 
     } 
     set 
     { 
      _authVal = value; 
      NotifyPropertyChanged("AuthResult"); 
     } 
    } 

public event PropertyChangedEventHandler PropertyChanged; 

    public void NotifyPropertyChanged(string propName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); 
    } 
} 

この現在の実装は正しくありません。私はそうのように私のモデルからのPropertyChanged通知に加入する必要があることを発見しました:「AuthResult」プロパティが更新されなければならないところ、私は表示されません

LoginModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(LoginModel_PropertyChanged); 

void LoginModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
{ 
    if(e.PropertyName == "Authenticated") 
    { 
     //do something 
    } 
} 

。私はAuthResult = _model.Authenticated;のようなIfステートメントで何かしますか?

EDITED:

と私のコンストラクタでは?

LoginModel _model; 

     public view1(LoginModel model) 
     { 
      _model = model; 
      InitializeComponent();   
     } 

答えて

1

モデルはあなたがビューからそれに直接結合することができますINotifyPropertyChangedインターフェイスを実装している場合:認証されたプロパティは、新しいに設定されるたびにLoginModelクラスは、PropertyChangedイベントを上げる必要があることを

<Button Content="Button" IsEnabled="{Binding Authenticated}" /> 

注意を値。

また、ビューモデルクラスを介してモデル全体の実体を公開することができます:

public class ViewModel 
{ 
    public ViewModel(LoginModel model) 
    { 
     Model = model; 
    } 

    public LoginModel Model { get; } 
} 

を...とこのようにそれにバインド:

<Button Content="Button" IsEnabled="{Binding Model.Authenticated}" /> 

それはまだその必要のモデルクラスですINotifyPropertyChangedインタフェースを実装し、変更通知を発行します。

もう1つの選択肢は、ビューモデルが、バインドできるモデルクラスの任意のプロパティをビューからラップすることです。その後、今度はモデルクラスのプロパティをラップするビューモデルクラスのプロパティにバインドし、このような何か:

public class ViewModel 
{ 
    private readonly LoginModel _model; 
    public ViewModel(LoginModel model) 
    { 
     _model = model; 
    } 

    public bool AuthResult 
    { 
     get 
     { 
      return _model.Authenticated; 
     } 
     set 
     { 
      _model.Authenticated = value; 
      NotifyPropertyChanged("AuthResult"); 
     } 
    } 
} 

<Button Content="Button" IsEnabled="{Binding AuthResult}" /> 

この後者のアプローチを使用する利点は、ビューは、モデルクラスになんら依存していないことです。これはビューモデルクラスにのみバインドされ、これはMVVMデザインパターンが通常実装される方法です。

ただし、ビューモデルの(ラッパー)プロパティにバインドし、モデルクラスのプロパティが設定されるたびにビューを更新したい場合、モデルはビューモデルに対して一方向に変更されたことを通知する必要がありますそれは何らかのイベントやそれに類するものを上げる必要があります。これは通常、INotifyPropertyChangedインタフェースを実装することを意味します。ビューモデルは、例えば、モデルのPropertyChangedイベントをサブスクライブし、モデルが更新されるたびにプロパティをバインドデータのために、独自のPropertyChangedイベントを上げることができます。

public class ViewModel 
{ 
    private readonly LoginModel _model; 

    public ViewModel(LoginModel model) 
    { 
     if (model == null) 
      throw new ArgumentNullException("model"); 

     _model = model; 
     _model.PropertyChanged += OnModelChanged; 
    } 

    private void OnModelChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "Authenticated") 
      NotifyPropertyChanged("AuthResult"); 
    } 

    public bool AuthResult 
    { 
     get 
     { 
      return _model.Authenticated; 
     } 
     set 
     { 
      _model.Authenticated = value; 
      NotifyPropertyChanged("AuthResult"); 
     } 
    } 
} 
+0

この回答は最終的に私の質問に答えた、ありがとう再びmm8。 – ganjeii

+1

2番目のオプションはMVVMではなく、 "Facade" – Fabio

1

ちょうどそのXAMLであなたのViewModelがあなたの周りの "ビルド" になります。このアプローチではModel

<CheckBox IsChecked="{Binding MyModel.Authenticated}" /> 

のプロパティをバインドすることができViewModelににメンバーとして

public class ViewModel 
{ 
    private Model _myModel; 
    public Model MyModel 
    { 
     get { return _myModel; } 
     set 
     { 
      if (Equals(_myModel, value)) return; 
      _myModel = value; 
      NotifyPropertyChanged(nameof(MyModel)); 
     } 
    } 
} 

をモデルを使用しますモデル。
このモデルにINotifyPropertyChangedを実装したくない場合は、前の例と同じように「Facade」クラスのモデルを作成してください。

public class ModelFacade : INotifyPropertyChanged 
{ 
    private Model _myModel; 

    public bool Authenticated 
    { 
     get { return _myModel.Authenticated; } 
     set 
     { 
      _myModel.Authenticated = value; 
      NotifyPropertyChanged(nameof(Authenticated)); 
     } 
    } 
} 

public class ViewModel 
{ 
    private ModelFacade _myModel; 
    public ModelFacade MyModel 
    { 
     get { return _myModel; } 
     set 
     { 
      if (Equals(_myModel, value)) return; 
      _myModel = value; 
      NotifyPropertyChanged(nameof(MyModel)); 
     } 
    } 
} 
+0

[OK]を、そしてちょうどでコントロールからmymodelというプロパティにバインド景色?あなたはNotifyPropertyChanged()の不完全さを残し、 'NotifyPropertyChanged(" MyModel ")'をアクチュアリーに読み込む必要がありますか? – ganjeii

+0

また、あなたの答えが不完全であると思われるモデルから特定の「認証済み」プロパティを取得するために探しています。しかし、私はどこから来ているのか理解しています。 – ganjeii

+1

あなたのビューでは 'MyModel.Authenticated'にバインドするか、ビューモデルでラッパープロパティを作成することができます:' public bool AuthResult {get {return MyModel.Authenticated; } '。後者の場合、 'NotifyPropertyChanged(" AuthResult ")'をMyModelプロパティのセッターに追加する必要があります。 – mechanic

関連する問題