Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#、WPF、MVVM和INotifyProperty已更改_C#_Wpf_Mvvm_Inotifypropertychanged - Fatal编程技术网

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事件?我希望能比“WPF”更具体。该事件和xaml中的绑定语句之间有什么联系

  • 为什么初始属性值会在启动时到达UI,而不是随后到达

  • 我更改了实现InotifyProperty的模拟器(模型)是正确的,还是应该是ViewModel这样做?如果ViewModel这样做,那么模型中的编程更改不会触发PropertyChanged,因此我不清楚正确的模式。我意识到我的ViewModel实际上是多余的,但这是由于项目的简单性;一个更复杂的模型将使ViewModel概念更难实现。我的理解是ViewModel是连接我的单元测试的地方

  • 问题是您在模型上提升了
    PropertyChanged
    ,但视图绑定到了ViewModel。因此,您的视图只订阅ViewModel事件(而不是模型事件)——这就是textbox未更新的原因——因为它从不接收
    PropertyChanged
    事件。一种可能的解决方案是在ViewModel中侦听Model
    PropertyChanged
    事件,并相应地在ViewModel上引发相同的事件

  • 正在传播初始值,因为ViewModel中的setter/getter是正确的,问题在于事件

  • 是的,您是正确的(请参见我的#1),您应该在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);
    }
    
  • 始终确保已设置为数据上下文的类的实例应实现INotifyPropertyChanged
  • 在您的情况下,Simulator实现INotifyPropertyChanged,但SimulatorViewModel设置为DataContext,在这种情况下,只有SimulatorViewModel中有更改,而不是Simulator中有更改,UI才会知道 你能做的是:


    您可以在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将包含一些逻辑,如保存、回滚编辑器中所做的更改、保存时显示进度条等。。。这