简单的小INotifyPropertyChanged实现 [英] Simple small INotifyPropertyChanged implementation
问题描述
说我有以下课程:
public MainFormViewModel
{
public String StatusText {get; set;}
}
将对StatusText的更改反映到与其绑定的任何控件中,最简单的最小方法是什么?
What is the easiest smallest way to get my changes to StatusText to reflect to any controls that bind to it?
很明显,我需要使用INotifyPropertyChanged,但是有没有一种很酷的方法来使我的代码不混乱?需要大量文件?等等?
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?
注意:如果这是骗子,那么我很抱歉.我进行了搜索,但没有找到任何东西,只是使用了 T4代码生成听起来不容易(至少要设置).
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).
推荐答案
不幸的是,C#没有提供一种简单的机制来自动执行此操作...它已经
Unfortunately C# doesn't offer an easy mechanism to do that automatically... It has been suggested to create a new syntax like this :
public observable int Foo { get; set; }
但我怀疑它是否会包含在该语言中...
But I doubt it will ever be included in the language...
一种可能的解决方案是使用AOP框架,例如 Postsharp ,那样,您只需要装饰自己的属性的属性:
A possible solution would to use an AOP framework like Postsharp, that way you just need to decorate your properties with an attribute:
public MainFormViewModel : INotifyPropertyChanged
{
[NotifyPropertyChanged]
public String StatusText {get; set;}
}
(还没有尝试过,但是我很确定Postsharp允许您做这种事情...)
(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 ;)
[Serializable]
public class NotifyPropertyChangedAttribute : LocationInterceptionAspect
{
public override void OnSetValue(LocationInterceptionArgs args)
{
object oldValue = args.GetCurrentValue();
object newValue = args.Value;
base.OnSetValue(args);
if (args.Instance is INotifyPropertyChanged)
{
if (!Equals(oldValue, newValue))
{
RaisePropertyChanged(args.Instance, args.LocationName);
}
}
}
private void RaisePropertyChanged(object instance, string propertyName)
{
PropertyChangedEventHandler handler = GetPropertyChangedHandler(instance);
if (handler != null)
handler(instance, new PropertyChangedEventArgs(propertyName));
}
private PropertyChangedEventHandler GetPropertyChangedHandler(object instance)
{
Type type = instance.GetType().GetEvent("PropertyChanged").DeclaringType;
FieldInfo propertyChanged = type.GetField("PropertyChanged",
BindingFlags.Instance | BindingFlags.NonPublic);
if (propertyChanged != null)
return propertyChanged.GetValue(instance) as PropertyChangedEventHandler;
return null;
}
}
请注意,您的类仍需要实现INotifyPropertyChanged
接口.您只是不必在属性设置器中显式引发该事件.
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.
这篇关于简单的小INotifyPropertyChanged实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!