[英]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。
這引出了幾個問題:
究竟應該掛進PropertyChanged事件? 我希望比“WPF”更具體。 該事件與xaml中的Binding語句之間的聯系是什么?
為什么初始屬性值在啟動時會到達UI,但后來卻沒有?
我是否有權使用模擬器(模型)實現INotifyPropertyChanged,或者它應該是ViewModel嗎? 如果ViewModel這樣做,那么模型中的程序化更改不會觸發PropertyChanged,所以我不清楚正確的模式。 我意識到我的ViewModel實際上是多余的,但這是由於項目的簡單性; 更復雜的一個會使ViewModel概念更加努力。 我的理解是ViewModel是我的單元測試接口的地方。
問題是您在模型上提升了PropertyChanged
,但您的視圖綁定到ViewModel。 因此,您的View僅訂閱ViewModel事件(而不是Model) - 這就是文本框未更新的原因 - 因為它永遠不會收到PropertyChanged
事件。 一種可能的解決方案是在ViewModel中偵聽Model PropertyChanged
事件並相應地在ViewModel上引發相同的事件。
正在傳播初始值,因為ViewModel中的setter / getter是正確的,問題出在事件中。
是的,你是對的(參見我的#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);
}
你能做的是:
您可以在Simulator類中公開某些事件或委托,並掛鈎SimulatorViewModel類中的某些方法。 然后,當Simulator類中的值發生更改時,調用將在SimulatorViewModel上獲取Execute的事件或委托,現在您可以從模擬器獲取更新的值並更新SimulatorViewModel中的屬性。 確保在類中使用不同的屬性
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.