C#、WPF、MVVM和INotifyProperty已更改
我感到困惑;我想我明白了我的错误C#、WPF、MVVM和INotifyProperty已更改,c#,wpf,mvvm,inotifypropertychanged,C#,Wpf,Mvvm,Inotifypropertychanged,我感到困惑;我想我明白了我的错误 我有一个小的WPF应用程序,它有一个前端主窗口类,中间是一个VIEW模型,后面是一个模型。p> 我的例子中的模型是模拟器类 SimulatorViewModel几乎是透明的,只是在MainWindow和Simulator之间连接属性 模拟器实现INotifyPropertyChanged,模拟器中的每个属性设置程序调用RaisePropertyChanged方法: private string serialNumber; public string Serial
我有一个小的WPF应用程序,它有一个前端主窗口类,中间是一个VIEW模型,后面是一个模型。p> 我的例子中的模型是模拟器类
SimulatorViewModel几乎是透明的,只是在MainWindow和Simulator之间连接属性 模拟器实现INotifyPropertyChanged,模拟器中的每个属性设置程序调用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中,我有一个具有如下绑定的文本框:
Text="{Binding Path=SerialNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DataContext是SimulatorViewModel(但请参阅我关于将DataContext更改为模型的注释)
ViewModel只是通过以下方式传递属性:
public string SerialNumber
{
get { return Simulator.SerialNumber; }
set { Simulator.SerialNumber = value; }
}
模拟器中对属性SerialNumber的编程更新不会传播到UI,尽管奇怪的是,模拟器构造函数中设置的初始值正在到达UI
如果我在模拟器中中断SerialNumber设置程序并进入RaisePropertyChanged,我会发现PropertyChanged为null,因此事件不会向上传播到GUI
这就引出了几个问题:
PropertyChanged
,但视图绑定到了ViewModel。因此,您的视图只订阅ViewModel事件(而不是模型事件)——这就是textbox未更新的原因——因为它从不接收PropertyChanged
事件。一种可能的解决方案是在ViewModel中侦听ModelPropertyChanged
事件,并相应地在ViewModel上引发相同的事件PropertyChanged
,因为视图已绑定到它。这些事件在模型更改后不会自动触发,因此您应该在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上执行的事件或委托,现在您可以从Simulator中获取更新的值并更新SimulatorViewModel中的属性。确保在两个类中使用不同的属性是否可以包括更新SerialNumber属性的代码?@devdigital-SerialNumber=GenerateSerialNumber();-我认为这不是问题所在。但我刚刚发现,如果我将DataContext设置为Simulator(模型),那么一切都可以正常工作。但这不意味着ViewModel是不相关的吗?SimulatorViewModel是什么样子的?从我所看到的,你的模拟器类扮演了ViewModel的角色。因此,目前您的SimulatorViewModel是冗余的。您是如何将模拟器通知传播到SimulatorViewModel的?@Goran:为了清晰起见,我在上面的代码中添加了一个SimulatorViewModel属性示例。是的,正如我所说,viewmodel在这样一个简单的情况下似乎并不重要,但在更复杂的情况下,它会很有用。我认为您将模拟器通知传播到SimulatorViewModel是正确的。是DataContext启动连接PropertyChanged事件的情况吗?这可以解释很多。但所有这些似乎都引出了一个问题:“ViewModel实际上有什么用途?”是的,这一切都是有道理的,谢谢。但是这个ViewModel的东西开始困扰我了。我通过视图模型(使用额外的代码)来反映我的所有属性,正如您所说,我可能需要使用事件(使用额外的代码)来监控viewmodel中的模型更改:我开始怀疑是否需要viewmodel,尽管我断言它在更复杂的项目中会很有用。在viewmodel中到底应该包含什么样的内容才能真正证明需要一个中间层?任何适合您的视图但在您的模型中没有意义的属性或表示逻辑都将包含在您的视图模型中。例如,您可能希望在视图中显示用户的年龄,但您的模型只有DateOfBirth属性。您可以使用诸如CSLA之类的框架来构建丰富的模型,您可以直接从视图绑定到这些模型,以保存模型->视图模型同步开销。@Alan,视图模型可能有许多不同的用例。对我来说,最常见的用例是VM应该是模型的编辑器。在这种情况下,VM将包含一些逻辑,如保存、回滚编辑器中所做的更改、保存时显示进度条等。。。这