簡體   English   中英

C#,WPF,MVVM和INotifyPropertyChanged

[英]C#, WPF, MVVM and INotifyPropertyChanged

我感到困惑; 我以為我理解了INotifyPropertyChanged。

我有一個小的WPF應用程序,前端是MainWindow類,中間有一個視圖模型,后面有一個模型。

我的模型是模擬器類。

SimulatorViewModel幾乎是透明的,只是MainWindow和Simulator之間的接口屬性。

Simulator實現了INotifyPropertyChanged,Simulator中的每個屬性setter都調用了RaisePropertyChanged方法:

private string serialNumber;
public string SerialNumber
{
    get { return serialNumber; }
    set
    {
        serialNumber = value;
        RaisePropertyChanged("SerialNumber");
    }
}

public event PropertyChangedEventHandler PropertyChanged;

public void RaisePropertyChanged(string propName)  
{  
    if (this.PropertyChanged != null)  
    {  
        this.PropertyChanged(this, new PropertyChangedEventArgs(propName));  
    }  
}    

在xaml中,我有一個帶有這樣綁定的TextBox:

Text="{Binding Path=SerialNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

並且DataContext是SimulatorViewModel(但是請參閱我關於將DataContext更改為模型的注釋)

ViewModel只傳遞屬性:

public string SerialNumber  
{  
    get { return Simulator.SerialNumber; }  
    set { Simulator.SerialNumber = value; }  
}  

Simulator中屬性SerialNumber的編程更新不會傳播到UI,但奇怪的是,在Simulator構造函數中設置的初始值正在到達那里。

如果我在模擬器中斷開SerialNumber setter並進入RaisePropertyChanged,我發現PropertyChanged為null,因此事件不會向上傳播到GUI。

這引出了幾個問題:

  1. 究竟應該掛進PropertyChanged事件? 我希望比“WPF”更具體。 該事件與xaml中的Binding語句之間的聯系是什么?

  2. 為什么初始屬性值在啟動時會到達UI,但后來卻沒有?

  3. 我是否有權使用模擬器(模型)實現INotifyPropertyChanged,或者它應該是ViewModel嗎? 如果ViewModel這樣做,那么模型中的程序化更改不會觸發PropertyChanged,所以我不清楚正確的模式。 我意識到我的ViewModel實際上是多余的,但這是由於項目的簡單性; 更復雜的一個會使ViewModel概念更加努力。 我的理解是ViewModel是我的單元測試接口的地方。

  1. 問題是您在模型上提升了PropertyChanged ,但您的視圖綁定到ViewModel。 因此,您的View僅訂閱ViewModel事件(而不是Model) - 這就是文本框未更新的原因 - 因為它永遠不會收到PropertyChanged事件。 一種可能的解決方案是在ViewModel中偵聽Model PropertyChanged事件並相應地在ViewModel上引發相同的事件。

  2. 正在傳播初始值,因為ViewModel中的setter / getter是正確的,問題出在事件中。

  3. 是的,你是對的(參見我的#1),你應該在ViewModel上引發PropertyChanged ,因為View綁定了它。 模型中的更改后,這些事件不會自動觸發,因此您應該在ViewModel中偵聽Model.PropertyChanged

理解這個想法最簡單的臟修復:

SimulatorViewModel(Simulator model)
{
    // this will re-raise Model's events on ViewModel
    // VM should implement INotifyPropertyChanged
    // method OnPropertyChanged should raise INPC for a given property
    model.PropertyChanged += (sender, args) => this.OnPropertyChanged(args.PropertyName);
}
  1. 始終確保已設置為Data-context的類的實例應實現INotifyPropertyChanged
  2. 在你的情況下,Simulator實現了INotifyPropertyChanged,但是SimulatorViewModel被設置為DataContext,在這種情況下,只有在SimulatorViewModel中有更改但在模擬器中沒有更改時,UI才會知道。

你能做的是:

您可以在Simulator類中公開某些事件或委托,並掛鈎SimulatorViewModel類中的某些方法。 然后,當Simulator類中的值發生更改時,調用將在SimulatorViewModel上獲取Execute的事件或委托,現在您可以從模擬器獲取更新的值並更新SimulatorViewModel中的屬性。 確保在類中使用不同的屬性

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM