简单的小型 INotifyPropertyChanged 实现
假设我有以下课程:
public MainFormViewModel
{
public String StatusText {get; set;}
}
使我对 StatusText 的更改反映到绑定到它的任何控件的最简单的最小方法是什么?
显然我需要使用 INotifyPropertyChanged,但是有没有一种很酷的方法可以做到这一点,并且不会使我的代码变得混乱?需要很多文件吗? ETC?
注意:如果这是一个骗局,那么我很抱歉。我搜索后找不到任何东西,但使用 T4 代码生成听起来并不容易(至少设置起来)。
Say I have the following class:
public MainFormViewModel
{
public String StatusText {get; set;}
}
What is the easiest smallest way to get my changes to StatusText to reflect to any controls that bind to it?
Obviously I need to use INotifyPropertyChanged, but is there a cool way to do it that does not clutter up my code? need lots of files? etc?
Note: If this is a dupe then I am sorry. I searched and could not find any thing but using T4 code Generation which does not sound easy (to setup at least).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不幸的是,C# 没有提供一种简单的机制来自动执行此操作...它已经 建议创建这样的新语法:
但我怀疑它是否会被包含在该语言中。 一个可能的
解决方案是使用像 Postsharp 这样的 AOP 框架,这样你只需要用属性:(
还没有尝试过,但我很确定 Postsharp 允许你做那种事情......)
更新:好的,我设法让它工作。请注意,这是一个非常粗略的实现,使用私有字段上的反射来检索委托...它当然可以改进,但我将把它留给您;)
请注意,您的类仍然需要实现 INotifyPropertyChanged接口。您只是不必在属性设置器中显式引发该事件。
Unfortunately C# doesn't offer an easy mechanism to do that automatically... It has been suggested to create a new syntax like this :
But I doubt it will ever be included in the language...
A possible solution would to use an AOP framework like Postsharp, that way you just need to decorate your properties with an attribute:
(haven't tried, but I'm pretty sure Postsharp allows you to do that kind of thing...)
UPDATE: OK, I managed to make it work. Note that it's a very crude implementation, using reflection on a private field to retrieve the delegate... It could certainly be improved, but I'll leave it to you ;)
Note that your class still need to implement the
INotifyPropertyChanged
interface. You just don't have to explicitly raise the event in your property setters.尝试一下http://code.google.com/p/notifypropertyweaver/
全部你需要做的是实现
INotifyPropertyChanged
所以你的代码看起来像
构建任务将编译这个(你永远不会看到下面的代码)
Have a go of this http://code.google.com/p/notifypropertyweaver/
All you need to do is implement
INotifyPropertyChanged
So your code will look like
The build task will compile this (you never see the below code)
通过利用EqualityComparer.Default,您可以减少属性setter 代码缩减为一行,如下所示:
如果您的视图模型继承自定义
SetProperty
方法和PropertyChanged
事件的基类,则支持所需的代码量子视图模型中的 INotifyPropertyChanged 变得非常小(1 行)。这种方法比其他答案中提到的代码编织方法更详细,但不需要您修改构建过程来完成它。
请务必查看即将发布的 C# 5 调用者信息属性 以及看起来它们将允许我们避免在方法中使用魔术字符串,而不需要反射的性能成本。
更新(2012 年 3 月 1 日):.
NET 4.5 Beta 已经发布,有了它,您可以进一步细化上述代码,从而消除了调用者中对字符串文字的需要:
我有一个 博客文章 对此进行了更详细的讨论。
By leveraging EqualityComparer.Default you can reduce the property setter code down to one line as follows:
If your view models inherit from a base class that defines the
SetProperty
method and thePropertyChanged
event, then the amount of code required to support INotifyPropertyChanged in your child view models becomes very minimal (1 line).This approach is more verbose then the code weaving methods mentioned in other answers, but doesn't require you to modify your build process to accomplish it.
Be sure to take a look at the upcoming C# 5 Caller Info attributes as well as it looks like they will allow us to avoid using a magic string in the method without the performance cost of reflection.
UPDATE (March 1st, 2012):
The .NET 4.5 Beta is out, and with it, you can further refine the above code to this which removes the need for the string literal in the caller:
I have a blog post that talks about it in slightly more detail.
我一直喜欢这种方法
或者减少代码膨胀
Ive always liked this method
or for less code bloat
我有一个名为“Model”的基类。它公开了一个名为 DataPoints 的受保护对象,它本质上是一个字典。
C#
VB
当您在 DataPoints 字典中设置值时,它会执行以下操作:
由于它是字典,因此它还使得从数据库或 XML 文件加载对象变得非常容易。
现在您可能认为读取和写入字典的成本很高,但我一直在进行大量性能测试,并且在我的 WPF 应用程序中没有发现这有任何明显的影响。
I have a base class called "Model". It exposes a protected object called DataPoints, which is essentially a dictionary.
C#
VB
When you set a value in the DataPoints dictionary it does the following:
Since it is a dictionary, it also makes loading objects from a database or XML file really easy.
Now you may think reading and writing to dictionary is expensive, but I've been doing a lot of performance testing and I haven't found any noticable impact from this in my WPF applications.
PropertyChanged.Fody
NuGet 包执行此操作。https://github.com/Fody/PropertyChanged
PropertyChanged.Fody
打包到您的项目中。using PropertyChanged;
[ImplementPropertyChanged]
属性添加到您的类中。类中的所有属性现在都将神奇地实现 INotifyPropertyChanged。注意 - Fody 通过修改发出的 IL 来工作,因此您永远不会在 VS 中实际看到代码 - 它只是神奇地做到了这一点。
附加文档:
https://github.com/Fody/PropertyChanged/wiki/Attributes
The
PropertyChanged.Fody
NuGet package does this.https://github.com/Fody/PropertyChanged
PropertyChanged.Fody
package to your project.using PropertyChanged;
[ImplementPropertyChanged]
attribute to your class.All of the properties in the class will now magically implement
INotifyPropertyChanged
. Note - Fody works by modifying the emitted IL so you will never actually see the code in VS - it just magically does it.Additional docs:
https://github.com/Fody/PropertyChanged/wiki/Attributes