C#,WPF,MVVM和INotifyPropertyChanged的 [英] C#, WPF, MVVM and INotifyPropertyChanged

查看:278
本文介绍了C#,WPF,MVVM和INotifyPropertyChanged的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我越来越糊涂;我想我明白INotifyPropertyChanged的。



我有一个前端MainWindow类的小WPF应用程序,在中间有一个视图模型,并在后面的典范。



在我的情况下,模型是模拟类。



SimulatorViewModel几乎是透明的,只是接口MainWindow,并将模拟器的性能。



模拟器实现INotifyPropertyChanged,并在模拟器每个属性setter调用RaisePropertyChanged方式:

 私人字符串的serialNumber; 
公共字符串的SerialNumber
{
{返回的serialNumber; }

{
的serialNumber =价值;
RaisePropertyChanged(的SerialNumber);
}
}

公共事件PropertyChangedEventHandler的PropertyChanged;

公共无效RaisePropertyChanged(字符串作为propName)
{
如果(this.PropertyChanged!= NULL)
{
this.PropertyChanged(这一点,新PropertyChangedEventArgs (的propName));
}
}

在XAML中,我有一个TextBox像绑定这样的:

 文本={绑定路径=的SerialNumber,模式=双向,UpdateSourceTrigger =的PropertyChanged}

和DataContext的是SimulatorViewModel(但看到我的有关更改的DataContext到模型评论)



视图模型只是通过传递属性:

 公共字符串的SerialNumber 
{
{返回Simulator.SerialNumber; }
集合{Simulator.SerialNumber =价值; }
}



编程更新在模拟器属性的SerialNumber不会传播到UI但奇怪的初始值,在模拟器构造函数中设置,越来越那里。



如果我打破了模拟器的serialNumber二传手,并按照成RaisePropertyChanged,我发现的PropertyChanged ,为空,因此该事件不会向上传播到GUI



这使我几个问题:




  1. 究竟应该挂钩到PropertyChanged事件是什么?我期待不仅仅是WPF更具体。什么是在XAML该事件,并绑定语句之间的联系?


  2. 为什么初始属性值在启动时起床到用户界面,但事后没有?


  3. 我说得对有模拟(模型)实施INotifyPropertyChanged的,还是应在ViewModel这样做?如果确实视图模型,然后在模型方案变动不会触发PropertyChanged的,所以我在正确的模式不清楚。我知道我的ViewModel几乎是多余的,但是这是由于项目的简单;更复杂的人会做的视图模型的概念更加努力地工作。我的理解是,视图模型是接口我的单元测试的地方。



解决方案

  1. 的问题是,你是在养的PropertyChanged 您的手机型号,但你的观点是必然视图模型。所以,你的浏览订阅只视图模型的事件(不是模特) - 这就是为什么没有更新,文本框 - 因为它永远不会收到的PropertyChanged 事件。其中一个可能的解决方案是在视图模型监听模式的PropertyChanged 事件并相应地对视图模型提高同一事件。


  2. 初始值被传播,因为你的制定者/视图模型中干将是正确的,问题是在事件。


  3. 是的,你是正确的(见我的#1),则应该增加的PropertyChanged 您的视图模型因为视图绑定到它。这些事件将不会在型号更改后自动触发,所以你应该听 Model.PropertyChanged 在视图模型。




最简单的脏修复理解的想法:

  SimulatorViewModel(仿真模型)
{
//这将重新提高模型对视图模型
事件// VM应实现INotifyPropertyChanged
//的方法OnPropertyChanged应提高INPC给定属性
model.PropertyChanged + =(发件人,参数)=> this.OnPropertyChanged(args.PropertyName);
}


I'm getting confused; I thought I understood INotifyPropertyChanged.

I have a small WPF app with a frontend MainWindow class, a viewmodel in the middle and a model at the back.

The model in my case is the Simulator class.

The SimulatorViewModel is nearly transparent and just interfaces properties between MainWindow and Simulator.

Simulator implements INotifyPropertyChanged and each property setter in Simulator calls the RaisePropertyChanged method:

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));  
    }  
}    

In the xaml, I have a TextBox with binding like this:

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

and the DataContext is the SimulatorViewModel (but see my comment about changing the DataContext to the model)

The ViewModel just passes the properties through:

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

Programmatic updates to the property SerialNumber in Simulator are not propagating up to the UI although curiously the initial value, set in the Simulator constructor, is getting there.

If I break on the SerialNumber setter in the Simulator and follow into RaisePropertyChanged, I find that PropertyChanged is null and so the event is not propagating upwards to the GUI.

Which leads me to several questions:

  1. What exactly should be hooking into the PropertyChanged event? I'm looking to be more specific than just "WPF". What's the link between that event and the Binding statement in the xaml?

  2. Why is the initial property value getting up to the UI at startup, but not subsequently?

  3. Am I right to have Simulator (the model) implementing INotifyPropertyChanged, or should it be the ViewModel doing that? If the ViewModel does it, then programmatic changes in the model don't trigger PropertyChanged, so I'm unclear on the correct pattern. I realise my ViewModel is virtually redundant, but that's due to the simplicity of the project; a more complex one would make the ViewModel concept work harder. My understanding is that the ViewModel is the place to interface my unit tests.

解决方案

  1. The problem is that you're raising PropertyChanged on your model, but your view is bound to ViewModel. So your View subscribes only to ViewModel events (not Model's) - that is why textbox is not updated - because it never receives PropertyChanged event. One of possible solutions is to listen in ViewModel for Model PropertyChanged events and raise same event on ViewModel accordingly.

  2. Initial value is being propagated because your setters/getters in ViewModel are correct, the problem is in events.

  3. Yes, you are correct (see my #1), you should raise PropertyChanged on your ViewModel because View is bound to it. These events will not be triggered automatically after changes in Model, so you should listen for Model.PropertyChanged in ViewModel.

Simplest dirty fix to understand the idea:

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);
}

这篇关于C#,WPF,MVVM和INotifyPropertyChanged的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆