wpf 当模型更改时刷新 ViewModel 的所有属性的数据绑定的好方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4651466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Good way to refresh databinding on all properties of a ViewModel when Model changes
提问by Dan J
Short Version
精简版
If I update the Model object that my ViewModel wraps, what's a goodway to fire property-change notifications for all the model's properties that my ViewModel exposes?
如果我更新 ViewModel 包装的 Model 对象,那么为我的 ViewModel 公开的所有模型属性触发属性更改通知的好方法是什么?
Detailed Version
详细版本
I'm developing a WPF client following the MVVM pattern, and am attempting to handle incoming updates, from a service, to data being displayed in my Views. When the client receives an update, the update appears in the form of a DTO which I use as a Model.
我正在按照 MVVM 模式开发 WPF 客户端,并尝试处理从服务到在我的视图中显示的数据的传入更新。当客户端收到更新时,更新以我用作模型的 DTO 的形式出现。
If this model is an update to an existing model being shown in the View, I want the associated ViewModel to update its databound properties so that the View reflects the changes.
如果此模型是对视图中显示的现有模型的更新,我希望关联的 ViewModel 更新其数据绑定属性,以便视图反映更改。
Let me illustrate with an example. Consider my Model:
让我用一个例子来说明。考虑我的模型:
class FooModel
{
public int FooModelProperty { get; set; }
}
Wrapped in a ViewModel:
包裹在一个 ViewModel 中:
class FooViewModel
{
private FooModel _model;
public FooModel Model
{
get { return _model; }
set
{
_model = value;
OnPropertyChanged("Model");
}
}
public int FooViewModelProperty
{
get { return Model.FooModelProperty; }
set
{
Model.FooModelProperty = value;
OnPropertyChanged("FooViewModelProperty");
}
}
The Problem:
问题:
When an updated model arrives, I set the ViewModel's Model property, like so:
当更新的模型到达时,我设置 ViewModel 的 Model 属性,如下所示:
instanceOfFooVM.Model = newModel;
This causes OnPropertyChanged("Model")
to fire, but not OnPropertyChanged("FooViewModelProperty")
, unless I call the latter explicitly from Model
's setter. So a View bound to FooViewModelProperty
won't update to display that property's new value when I change the Model.
这会导致OnPropertyChanged("Model")
触发,但不会触发,OnPropertyChanged("FooViewModelProperty")
除非我从Model
的 setter 中明确调用后者。因此FooViewModelProperty
,当我更改模型时,绑定到的视图不会更新以显示该属性的新值。
Explicitly calling OnPropertyChanged
for every exposed Model property is obviously not a desirable solution, and neither is taking the newModel
and iterating through its properties to update the ViewModel's properties one-by-one.
显式调用OnPropertyChanged
每个暴露的 Model 属性显然不是一个理想的解决方案,而且也不是newModel
通过它的属性进行迭代来更新 ViewModel 的属性。
What's a better approach to this problem of updating a whole model and needing to fire change notifications for all its exposed properties?
有什么更好的方法可以解决更新整个模型并需要为其所有公开属性触发更改通知的问题?
回答by Joe White
回答by Reed Copsey
One option is to listen to your own events, and make a helper routine to raise the other notifications as required.
一种选择是侦听您自己的事件,并根据需要制定帮助程序以引发其他通知。
This can be as simple as adding, in your constructor:
这可以像在构造函数中添加一样简单:
public FooViewModel()
{
this.PropertyChanged += (o,e) =>
{
if (e.PropertyName == "Model")
{
OnPropertyChanged("FooViewModelProperty");
// Add other properties "dependent" on Model here...
}
};
}
回答by Jon
Whenever your Model
property is set, subscribe to its own PropertyChanged
event. When your handler gets called, fire off your own PropertyChanged
event. When the Model
is set to something else, remove your handler from the old Model
.
每当您的Model
属性被设置时,订阅它自己的PropertyChanged
事件。当您的处理程序被调用时,触发您自己的PropertyChanged
事件。当Model
设置为其他内容时,从旧的Model
.
Example:
例子:
class FooViewModel
{
private FooModel _model;
public FooModel Model
{
get { return _model; }
set
{
if (_model != null)
{
_model.PropertyChanged -= ModelPropertyChanged;
}
if (value != null)
{
value.PropertyChanged += ModelPropertyChanged;
}
_model = value;
OnPropertyChanged("Model");
}
}
public int FooViewModelProperty
{
get { return Model.FooModelProperty; }
set
{
Model.FooModelProperty = value;
OnPropertyChanged("FooViewModelProperty");
}
}
private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Here you will need to translate the property names from those
// present on your Model to those present on your ViewModel.
// For example:
OnPropertyChanged(e.PropertyName.Replace("FooModel", "FooViewModel"));
}
}
回答by VampireMonkey
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(String.Empty))
For VB.net if anybody else needs it. If you have already implemented "INotifyPropertyChanged" then the last line is all you need.
对于 VB.net,如果其他人需要它。如果您已经实现了“INotifyPropertyChanged”,那么最后一行就是您所需要的。