INotifyPropertyChanged与ViewModel中的DependencyProperty
当在Model-View-ViewModel体系结构的WPF应用程序中实现ViewModel时,似乎有两个主要的select如何使它成为数据绑定的。 我见过使用DependencyProperty
实现视图将要绑定的属性,我已经看到实现INotifyPropertyChanged
的ViewModel。
我的问题是我应该什么时候比另一个更喜欢? 有任何性能差异? 将ViewModel依赖关系提供给WPF真的是个好主意吗? 做出devise决定时还需要考虑什么?
肯特写了一个有趣的博客关于这个话题: 查看模型:POCOs与DependencyObjects 。
简短的摘要:
- DependencyObjects不被标记为可序列化
- DependencyObject类重写并封闭了Equals()和GetHashCode()方法
- 一个DependencyObject具有线程相关性 – 它只能在创build它的线程上访问
我更喜欢POCO方法。 实现INotifyPropertyChanged接口的PresentationModel(aka ViewModel)的基类可以在这里find: http : //compositeextensions.codeplex.com
根据WPF性能指南,DependencyObjects绝对比执行INotifyPropertyChanged的POCO执行得更好:
select完全基于您的业务逻辑和UI抽象级别。 如果你不想要一个很好的分离,那么DP将为你工作。
DependencyProperties将主要适用于VisualElements级别,所以如果我们为每个业务需求创build大量的DP,将不是一个好主意。 DP比INotifyPropertyChanged还要花费更多。 当你devise一个WPF / Silverlight尝试deviseUI和ViewModel完全分离,以便在任何时候我们可以改变布局和UI控件(基于主题和样式)
也请参考这篇文章 – https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel 。 该链接有很多对Model-View-ViewModel模式的引用,这与这个讨论非常相关。
从performance力的angular度来看,我完全喜欢使用依赖属性,并且非常喜欢INotifyPropertyChanged
。 除了string
属性名称和事件订阅可能的内存泄漏, INotifyPropertyChanged
是一个更为明确的机制。
使用易于理解的静态元数据,依赖属性意味着“何时这样做”。 这是一个声明性的方法,让我的投票优雅。
当使用INotifyPropertyChanged
时,还可以在您的getter和setter属性的代码中添加更多逻辑。
DependencyProperty
示例:
public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) ); public String Name { set { SetValue( NameProperty, value ); } get { return ( String ) GetValue( NameProperty ); } }
在你的getter和setter中—你所能做的只是简单地分别调用SetValue和GetValue,在框架的其他部分b / c getter / setter不被调用,而是直接调用SetValue,GetValue,所以你的属性逻辑wouldnt可靠地执行。
使用INotifyPropertyChanged
,定义一个事件:
public event PropertyChangedEventHandler PropertyChanged;
然后,只需在代码中的任何地方使用逻辑,然后调用:
// ... // Something cool... // ... if( this.PropertyChanged != null ) { PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) ); } // More cool stuff that will reliably happen...
这可能是在一个getter / setter,或其他地方。
依赖属性旨在支持在UI元素上绑定(作为目标),而不是作为数据绑定的源,这是INotifyProperty进来的地方。从纯粹的angular度来看,您不应该在ViewModels上使用DP。
“为了成为一个绑定的来源,一个属性不需要是一个依赖属性,你可以使用任何CLR属性作为绑定源,但是为了成为一个绑定的目标,属性必须是依赖项属性为了使单向或双向绑定有效,源属性必须支持传播到绑定系统和目标的更改通知,对于自定义的CLR绑定源,这意味着属性必须支持INotifyPropertyChanged。集合应该支持INotifyCollectionChanged。“
所有依赖项对象都不能被序列化(这可能妨碍ViewModel和DTO(POCO)的使用。
Silverlight中的DP与WPF相比有所不同。
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
我最近也不得不考虑这个决定。
我发现INotifyPropertyChanged机制更适合我的需求,因为它允许我粘贴我的GUI到现有的业务逻辑框架而不复制状态。 我使用的框架有自己的观察者模式,很容易将一个级别的通知转发到下一个。 我只是有一个类实现了我的业务逻辑框架和INotifyPropertyChanged接口的观察者接口。
使用DP,您无法定义自己存储状态的后端。 我将不得不让.netcaching我绑定到的每个状态项的副本。 这似乎是不必要的开销 – 我的状态是庞大而复杂的。
所以在这里我发现INotifyPropertyChanged更适合将业务逻辑的属性暴露给GUI。
这就是说,我需要一个自定义的GUI小部件来公开一个属性和更改该属性来影响其他GUI小部件DPcertificate了简单的解决scheme。
所以我发现DP对GUI通知有用。
将ViewModel依赖关系提供给WPF真的是个好主意吗?
.NET 4.0将有System.Xaml.dll,所以你不必依赖任意的框架来使用它。 请参阅Rob Relyea关于他的PDC会话的文章。
我的
XAML是一种用于描述对象的语言,WPF是一个描述对象是UI元素的框架。
它们的关系类似于C#,一种描述逻辑的语言,.NET,一种实现特定types逻辑的框架。
XAML的目的是声明对象图。 W * F技术非常适合这种范式,但是XAML独立存在。
XAML和整个依赖系统被作为WF和WPF的独立栈来实现,可能会利用不同团队的经验,而不会在它们之间创build依赖关系(无双关语意图)。
看起来,依赖属性应该用在你创build的控件中,比如button。 要在XAML中使用属性并使用所有的WPFfunction,那些属性必须依赖于属性。
但是,您的ViewModel最好使用INotifyPropertyChanged。 如果需要,使用INotifyPropertyChanged将使您具有获取/设置逻辑的能力。
我build议查看一下已经实现INotifyPropertyChanged的ViewModel的Josh Smith版本的基类:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
我认为这是如何做一个ViewModel的一个很好的例子。
我认为DependencyProperty和INotifyPropertyChanged在Binding中用于两个不同的事情:第一个用于使属性成为绑定的目标并从另一个属性接收input(使用{Binding …}来设置属性),最后当您想要将某个属性的值用作绑定的源(绑定pathexpression式中的名称)时。 所以select仅仅是技术性的。
依赖属性是自定义控件创build的粘合剂。 如果您有兴趣使用Intelli-sense在XAMLdevise时的属性窗口中显示属性,则必须使用依赖项属性。 INPC绝不会在devise时在房产窗口中显示房产。
我更喜欢更直接的方法,我没有INotifyPropertyChanged在Presentation Model中发表了博文。 使用数据绑定的替代方法,您可以直接绑定到CLR属性,而无需任何簿记代码。 您只需在View Model中编写纯旧的.NET代码,并在数据模型更改时进行更新。
只有一件事情,为什么喜欢一个DependencyObject
– 绑定会更好。 只要尝试一个ListBox
和TextBox
的例子,用INotifyPropertyChanged
属性与DependencyProperty
数据填充列表,并从TextBox
编辑当前项目…
如果你想暴露其他控件的属性,你必须使用依赖属性…但是,祝你好运,因为他们需要一段时间来弄清楚…