我有一个在后台更新自己的模型。目前我在模型上使用INotifyPropertyChanged,但我被告知这是一个坏主意,因为模型应该与UI无关。
当模型在MVVM设计模式中发生变化时,是否存在更新ViewModel的首选模式?
答案 0 :(得分:3)
两条评论:
例如:
class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public MyViewModel(MyModel mdl)
{
mdl.PropertyChanged +=
new PropertyChangedEventHandler(
mdl_PropertyChanged);
_mdl = mdl;
}
private MyModel _mdl = null;
void mdl_PropertyChanged(object sender,
PropertyChangedEventArgs e)
{
if (e.PropertyName == "Foo")
{
this.Foo = _mdl.Foo;
}
}
public int Foo
{
get
{
lock(_foo_Lock)
{
return _foo;
}
}
set
{
lock(_foo_Lock)
{
_foo = value;
}
NotifyPropertyChanged("Foo");
}
}
private readonly object _foo_Lock = new object();
private int _foo = 0;
}
编辑:我实际上并不建议您使用硬编码字符串作为属性名称。这是一个helper class,您可以使用反射在构造期间获取属性名称。然后创建一个AbstractViewModel基类。然后,您可以从AbstractViewModel继承并实现如下属性:
#region IsCheckable
public bool IsCheckable
{
get
{
lock(m_IsCheckable_Lock)
{
return m_IsCheckable;
}
}
protected set
{
bool fire = false;
lock(m_IsCheckable_Lock)
{
if (m_IsCheckable != value)
{
m_IsCheckable = value;
fire = true;
}
}
if(fire)
{
NotifyPropertyChanged(m_IsCheckableArgs);
}
}
}
private readonly object m_IsCheckable_Lock = new object();
private bool m_IsCheckable = false;
static readonly PropertyChangedEventArgs m_IsCheckableArgs =
NotifyPropertyChangedHelper.CreateArgs<MyViewModel>(o =>
o.IsCheckable);
#endregion
答案 1 :(得分:2)
该模型应该与UI无关。
......好吧,模型当然不应该是意识到的View,这就是为什么你要让你的模型(或ViewModel)实现INotifyPropertyChanged,所以View可以绑定到Model上的Properties (或VM),让框架的更改通知告知更改视图(因此您的模型不需要)
当然,如果您根据后台线程中的数据更改UI,则需要安全地将它们分派到UI线程 - 您可以使用标准.net线程机制(如BackgroundWorker)或者您可以使用WPF的Dispatcher类。
答案 2 :(得分:0)
ViewModel的目的是允许模型独立。
让viewmodel监听模型中的事件
public MyViewModel(IView view, IModel model) {
model.SomeEvent += HandleSomeEvent;
....
}
如果你想发送INotifyPropertyChanged,你需要先切换到uithread。
(如果您的模型比viewmodel长,您应该查看一些弱参考事件模式以允许GC清理视图模型)