wpf INotifyPropertyChanged 与 ViewModel 中的 DependencyProperty
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/291518/
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
INotifyPropertyChanged vs. DependencyProperty in ViewModel
提问by bitbonk
When implementing the ViewModel in a Model-View-ViewModel architecture WPF application there seem to be two major choices how to make it databindable. I have seen implementations that use DependencyProperty
for properties the View is going to bind against and I have seen the ViewModel implementing INotifyPropertyChanged
instead.
在 Model-View-ViewModel 架构 WPF 应用程序中实现 ViewModel 时,似乎有两个主要选择如何使其可数据绑定。我已经看到了DependencyProperty
用于视图将绑定的属性的实现,并且我已经看到了 ViewModel 的实现INotifyPropertyChanged
。
My question is when should I prefer one over the other? Are there any performance differences? Is it really a good idea to give the ViewModel dependencies to WPF? What else do I need to consider when make the design decision?
我的问题是我什么时候应该更喜欢一个?是否有任何性能差异?将 ViewModel 依赖项提供给 WPF 真的是个好主意吗?在做出设计决定时,我还需要考虑什么?
采纳答案by jbe
Kent wrote an interesting blog about this topic: View Models: POCOs versus DependencyObjects.
Kent 写了一篇关于这个主题的有趣博客:View Models: POCOs vs DependencyObjects。
Short summary:
简短的摘要:
- DependencyObjects are not marked as serializable
- The DependencyObject class overrides and seals the Equals() and GetHashCode() methods
- A DependencyObject has thread affinity – it can only be accessed on the thread on which it was created
- DependencyObjects 未标记为可序列化
- DependencyObject 类覆盖并密封了 Equals() 和 GetHashCode() 方法
- DependencyObject 具有线程关联性——它只能在创建它的线程上访问
I prefer the POCO approach. A base class for PresentationModel (aka ViewModel) which implements INotifyPropertyChanged interface can be found here: http://compositeextensions.codeplex.com
我更喜欢 POCO 方法。可以在此处找到实现 INotifyPropertyChanged 接口的 PresentationModel(又名 ViewModel)的基类:http: //compositeextensions.codeplex.com
回答by James Ashley
According to the WPF performance guide, DependencyObjects definitely perform better than POCOs that implement INotifyPropertyChanged:
根据 WPF 性能指南,DependencyObjects 肯定比实现 INotifyPropertyChanged 的 POCO 性能更好:
回答by Jobi Joy
The choice is totally based on your business logic and UI abstraction level. If you dont want a good separation then DP will work for you.
选择完全基于您的业务逻辑和 UI 抽象级别。如果您不想要良好的分离,那么 DP 将为您工作。
DependencyProperties will be applicable mainly at the VisualElements level so it won't be good idea if we create lot of DPs for each of our business requirements. Also there is a greater cost for DP than a INotifyPropertyChanged. When you design a WPF/Silverlight try to design UI and ViewModel totally separate so that at any point of time we can change the Layout and UI controls (Based on theme and Styles)
DependencyProperties 将主要适用于 VisualElements 级别,因此如果我们为每个业务需求创建大量 DP 将不是一个好主意。DP 的成本也比 INotifyPropertyChanged 更高。当您设计 WPF/Silverlight 时,尝试将 UI 和 ViewModel 完全分开设计,以便我们可以随时更改布局和 UI 控件(基于主题和样式)
Refer this post also - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel. The link has a lot of reference to Model-View-ViewModel pattern, which is very relevant to this discussion.
另请参阅这篇文章 - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel。链接中有很多关于Model-View-ViewModel模式的参考,与本次讨论非常相关。
回答by Bryan Watts
From an expressiveness standpoint, I thoroughly enjoy using dependency properties and cringe at the thought of INotifyPropertyChanged
. Apart from the string
property names and possible memory leaks due to event subscription, INotifyPropertyChanged
is a much more explicit mechanism.
从表现力的角度来看,我非常喜欢使用依赖属性,一想到INotifyPropertyChanged
. 除了string
由于事件订阅而导致的属性名称和可能的内存泄漏之外,INotifyPropertyChanged
还有一种更加明确的机制。
Dependency properties imply "when this, do that" using easily-understood static metadata. It is a declarative approach that gets my vote for elegance.
依赖属性使用易于理解的静态元数据暗示“当这个,做那个”。这是一种声明式方法,让我为优雅投票。
回答by Adam
INotifyPropertyChanged
when used also gives you the ability to add more logic in the code of your getters and setter of your properties.
INotifyPropertyChanged
使用时,您还可以在属性的 getter 和 setter 代码中添加更多逻辑。
DependencyProperty
example:
DependencyProperty
例子:
public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );
public String Name
{
set { SetValue( NameProperty, value ); }
get { return ( String ) GetValue( NameProperty ); }
}
In your getter and setter --- all you can do is simply call SetValue and GetValue respectively, b/c in other parts of the framework the getter/setter is not called, instead it directly calls SetValue, GetValue, so your property logic wouldnt reliably be executed.
在你的 getter 和 setter --- 你能做的只是分别调用 SetValue 和 GetValue,在框架的其他部分 b/c 不调用 getter/setter,而是直接调用 SetValue、GetValue,所以你的属性逻辑不会可靠地执行。
With INotifyPropertyChanged
, define an event:
用INotifyPropertyChanged
,定义一个事件:
public event PropertyChangedEventHandler PropertyChanged;
And then simply have any logic anywhere in your code, then call:
然后只需在代码中的任何位置添加任何逻辑,然后调用:
// ...
// Something cool...
// ...
if( this.PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}
// More cool stuff that will reliably happen...
This could be in a getter/setter, or anywhere else.
这可以在 getter/setter 或其他任何地方。
回答by Nick Hermans
Dependency properties are intended to supports binding (as a target) on UI elements not as a source to data binding, this is where INotifyProperty comes in. From a pure point of view you shouldn't use DP on a ViewModels.
依赖属性旨在支持 UI 元素上的绑定(作为目标),而不是作为数据绑定的源,这就是 INotifyProperty 的用武之地。从纯粹的角度来看,您不应该在 ViewModel 上使用 DP。
"In order to be the source of a binding, a property does not need to be a dependency property; you can use any CLR property as a binding source. However, in order to be the target of a binding, the property must be a dependency property. For a one-way or two-way binding to be effective, the source property must support change notifications that propagate to the binding system and thus the target. For custom CLR binding sources, this means that the property must support INotifyPropertyChanged. Collections should support INotifyCollectionChanged."
“为了成为绑定的源,属性不需要是依赖属性;您可以使用任何 CLR 属性作为绑定源。但是,为了成为绑定的目标,该属性必须是一个依赖属性。要使单向或双向绑定有效,源属性必须支持传播到绑定系统并因此传播到目标的更改通知。对于自定义 CLR 绑定源,这意味着该属性必须支持 INotifyPropertyChanged。集合应支持 INotifyCollectionChanged。”
All dependency objects cannot be serialised (This could hamper the use of ViewModels and DTO (POCO)'s.
所有依赖对象都无法序列化(这可能会妨碍 ViewModel 和 DTO (POCO) 的使用。
There are differences between DP within Silverlight compared to WPF.
与 WPF 相比,Silverlight 中的 DP 之间存在差异。
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
回答by morechilli
I too had to consider this decision recently.
我最近也不得不考虑这个决定。
I found that the INotifyPropertyChanged mechanism suited my needs better because it allowed me to glue my GUI to an existing business logic framework without duplicating state. The framework I was using had its own observer pattern and it was easy to forward one level of notification on to the next. I simply had a class which implemented the observer interface from my business logic framework and the INotifyPropertyChanged interface.
我发现 INotifyPropertyChanged 机制更适合我的需求,因为它允许我将 GUI 粘合到现有的业务逻辑框架上,而无需复制状态。我使用的框架有它自己的观察者模式,并且很容易将一个级别的通知转发到下一个级别。我只是有一个从我的业务逻辑框架和 INotifyPropertyChanged 接口实现观察者接口的类。
With DP you cannot define the backend that stores the state yourself. I would have had to let .net cache a copy of every item of state I was binding to. This seemed like an unnecessary overhead - my state is large and complicated.
使用 DP,您无法定义自己存储状态的后端。我不得不让 .net 缓存我绑定到的每个状态项的副本。这似乎是不必要的开销 - 我的状态又大又复杂。
So here I found INotifyPropertyChanged better for exposing properties from business logic to GUI.
所以在这里我发现 INotifyPropertyChanged 更好地将业务逻辑中的属性暴露给 GUI。
That being said where I needed a custom GUI widget to expose a property and for changes to that property to affect other GUI widgets DP proved the simple solution.
话虽如此,我需要一个自定义 GUI 小部件来公开一个属性,并且对该属性的更改以影响其他 GUI 小部件 DP 证明了简单的解决方案。
So there I found DP useful for GUI to GUI notification.
所以我发现 DP 对 GUI 到 GUI 通知很有用。
回答by Bryan Watts
Is it really a good idea to give the ViewModel dependencies to WPF?
将 ViewModel 依赖项提供给 WPF 真的是个好主意吗?
.NET 4.0 will have System.Xaml.dll, so you won't have to take a dependency on an arbitrary framework to utilize it. See Rob Relyea'spost about his PDC session.
.NET 4.0 将具有 System.Xaml.dll,因此您不必依赖于任意框架来使用它。请参阅Rob Relyea关于他的 PDC 会话的帖子。
My take
我的看法
XAML is a language for describing objects, and WPF is a framework whose described objects are UI elements.
XAML 是一种描述对象的语言,而 WPF 是一个框架,其描述的对象是 UI 元素。
Their relationship is similar to C#, a language for describing logic, and .NET, a framework which implements particular kinds of logic.
它们的关系类似于 C#(一种描述逻辑的语言)和 .NET(一种实现特定类型逻辑的框架)。
XAML's purpose is declarative object graphs. The W*F technologies are great candidates for this paradigm, but XAML exists independently of them.
XAML 的目的是声明性对象图。W*F 技术是这种范式的绝佳候选者,但 XAML 独立于它们而存在。
XAML and the entire dependency system were implemented as separate stacks for WF and WPF, probably to leverage the experience of different teams without creating a dependency (no pun intended) between them.
XAML 和整个依赖项系统作为 WF 和 WPF 的单独堆栈实现,可能是为了利用不同团队的经验,而不会在它们之间创建依赖项(没有双关语)。
回答by John Peters
Dependency properties are the glue of custom control creation. If you are interested in using Intelli-sense to show your properties in the properties window at XAML design time you must use Dependency properties. INPC will never show a property in the property window at design time.
依赖属性是自定义控件创建的粘合剂。如果您有兴趣在 XAML 设计时使用 Intelli-sense 在属性窗口中显示您的属性,则必须使用依赖项属性。INPC 永远不会在设计时在属性窗口中显示属性。
回答by timothymcgrath
It seems that Dependency Properties should be used in controls that you create such as Buttons. To use properties in XAML and use all the WPF features, those properties must Dependency Properties.
似乎应该在您创建的控件(例如按钮)中使用依赖项属性。若要在 XAML 中使用属性并使用所有 WPF 功能,这些属性必须依赖属性。
However, your ViewModel is better off using INotifyPropertyChanged. Using INotifyPropertyChanged will give you the ability to have getter/setter logic if you need to.
但是,您的 ViewModel 最好使用 INotifyPropertyChanged。如果需要,使用 INotifyPropertyChanged 将使您能够拥有 getter/setter 逻辑。
I recommend checking out Josh Smith's version of a base class for a ViewModel that already implements INotifyPropertyChanged:
我建议查看 Josh Smith 的已实现 INotifyPropertyChanged 的 ViewModel 的基类版本:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
I think this is an excellent example of how to do a ViewModel.
我认为这是如何做 ViewModel 的一个很好的例子。