[英]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.