我第一次尝试使用MVVM。我有一个Windows Phone应用程序(Mango),它有一个模型类,一个视图模型类和一个视图xaml页面。我有控制(文本框)绑定到VM,并且VM绑定到模型。
模型和视图模型都实现了INotifyPropertyChanged
。我正在使用的实现被复制,以便我可以使用它来试图找出我正在使用INPC做什么。以下是两个类中列出的代码:
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
我在Model类中有一个属性,可以手动(从文本框)设置或计算(通过更改其他属性之一)。我们称之为一个结果。
如果我更改其他属性之一并逐步执行,则在模型类中的已更改属性和重新计算属性中都会调用INPC,尽管PropertyChanged
为null
,因此代码被跳过。然后在VM中,已更改的属性逐步执行该类'INPC(作为set访问器的一部分),而这次PropertyChanged
不是null
,因此PropertyChanged
方法是调用。但是,对于Result
属性,不会引发INPC(该属性没有由其他属性的set访问器调用的INPC)。
以下是Model中的一个属性,它不是计算属性:
public int AgeSetting
{
get
{
return (int)GetValueOrDefault(AgeSettingKeyName, AgeSettingDefault);
}
set
{
AddOrUpdateValue(AgeSettingKeyName, value);
Calculate();
}
}
以下是模型中计算值的属性。
public int PointsSetting
{
get
{
return (int)GetValueOrDefault(PointsSettingKeyName, PointsSettingDefault);
}
set
{
AddOrUpdateValue(PointsSettingKeyName, value);
}
}
从ViewModel,这里有两个属性:
public int Age
{
get
{
return person.AgeSetting;
}
set
{
person.AgeSetting = value;
NotifyPropertyChanged("Age");
}
}
public int PointsAllowed
{
get
{
return person.PointsSetting;
}
set
{
person.PointsSetting = value;
NotifyPropertyChanged("PointsAllowed");
}
}
之前从未这样做过,我期待INPC应该从模型类,VM类和UI中冒出来。它似乎没有那样工作。
我知道Result(计算)属性正在改变,因为我可以离开页面并返回,并且新显示的值是正确的。我只是不知道如何从模型中的计算值,到视图模型,直到视图。
感谢您提出任何建议。
答案 0 :(得分:5)
如果计算属性的值发生更改,则还会引发该属性的PropertyChanged事件。这意味着当单个属性发生更改时,可能会为多个属性触发事件。
此外,如果您的设计中可能/智能,您可以直接绑定到模型属性并使Model成为ViewModel的属性。这大大减少了代码维护。
答案 1 :(得分:3)
对于依赖于其他属性值的属性,程序员可以通知多个属性已更改。
给定一个具有三个属性的类 - Score,Multiplier和Total - 其中Total取决于Score和Multiplier的值,我可以像这样编写类:
public class ViewModel
{
private int score;
public int Score
{
get
{
return this.score;
}
set
{
if (this.score != value)
{
this.score = value;
// Notify that this property has changed
NotifyOfPropertyChange(() => this.Score);
// Notify that a dependant property has changed
NotifyOfPropertyChange(() => this.Total);
}
}
}
private int multiplier;
public int Multiplier
{
get
{
return this.multiplier;
}
set
{
if (this.multiplier != value)
{
this.multiplier = value;
// Notify that this property has changed
NotifyOfPropertyChange(() => this.Multiplier);
// Notify that a dependant property has changed
NotifyOfPropertyChange(() => this.Total);
}
}
}
public int Total
{
get
{
return this.Score * this.Multiplier;
}
}
}
例如,您会注意到,当我设置Score的值时,我会通知Score和Total都已更改。你对NotifyOfPropertyChange的具体启示与我的不同,但中心思想是一样的。因为Total是依赖于其他属性值的属性,所以它永远不会通知。相反,Total所依赖的属性负责通知。
答案 2 :(得分:1)
在模型中,在计算属性的setter中调用NotifyPropertyChanged方法。您应用中的某些逻辑应该是更新模型。确保ViewModel订阅了此事件。这非常重要,因为我认为这正是你在这里所缺少的。
然后,在ViewModel中的EventHandler中,订阅了一个Model on PropertyChanged事件,更改ViewModel的相应属性值(此处视图模型中的方法更新视图模型中的属性),UI被绑定至。
答案 3 :(得分:1)
听起来您还没有在模型类上实现INotifyPropertyChanged接口。如果没有这个,你的事件处理程序在被调用时将为null。
public class ViewModel : INotifyPropertyChanged
{
// Stuff
}
public class Model : INotifyPropertyChanged
{
// Stuff
}
另请查看我的博客,了解一些MVVM的内容。我有一些教程以及一些在不使用字符串值的情况下触发Inotify的方法(使用反射代替)。