C# 实现INotifyPropertyChanged时的属性获取程序和设置程序?
我试图为许多类实现INotifyPropertyChanged,这些类中的每一个都有很多属性。我一直在关注如何实现INofifyPropertyChanged,但它们的指令在类具有许多属性的情况下似乎并不实用 目前,我的大多数酒店都使用速记:C# 实现INotifyPropertyChanged时的属性获取程序和设置程序?,c#,.net,winforms,inotifypropertychanged,C#,.net,Winforms,Inotifypropertychanged,我试图为许多类实现INotifyPropertyChanged,这些类中的每一个都有很多属性。我一直在关注如何实现INofifyPropertyChanged,但它们的指令在类具有许多属性的情况下似乎并不实用 目前,我的大多数酒店都使用速记: public DateTime? DateClosed { get; set; } 但是文档说我需要在每个setter方法中添加以下内容: // Call OnPropertyChanged whenever the property is update
public DateTime? DateClosed { get; set; }
但是文档说我需要在每个setter方法中添加以下内容:
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
这意味着我需要为get方法声明一个主体,并声明私有变量来处理属性的实际获取和设置。像这样:
private DateTime? _dateOfIncident = null;
public DateTime? DateClosed
{
get { return _dateOfIncident; }
set
{
_dateOfIncident= value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
}
}
有人知道怎么解决这个问题吗 我不确定你是否能在这里找到解决办法。现在使用的自动属性实际上只是一个编译器速记,最终会通过一个支持字段转换为完整属性(至少,据我所知) INPC的使用是一种例行程序,与正常财产的职责有点分离。它通知订阅者(通常是您的视图XAML)相关属性已更改或正在更改 tl;dr--您无法避免将自动属性重写为具有备份字段的完整属性。但是像这样的工具包有一些很棒的VisualStudio代码片段,可以相对快速地实现这一点。最终你甚至可以这样做:
private string _someString;
public string SomeString
{
get { return _someString;}
set
{
//Set returns bool, so you can trigger other logic on it!
Set(() => SomeString, ref _someString, value);
}
}
这为您提供了一些简洁的功能:
- 强命名(与示例中的魔术字符串不同)
仅在值不同时触发INPC事件Set
返回布尔值,以便在值更改时可以执行更多操作Set
MVVMLight很好,因为您不必使用它的所有特性,甚至不必实现MVVM模式。它有很多不错的“工具”,你可以利用。有很多模式可以做,或者你可以买一个工具来帮你做 例如,这里有一种方法:
public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
private Dictionary<string, object> _valueStore = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected T Get<T>([CallerMemberName]string property = null)
{
object value = null;
if (!_valueStore.TryGetValue(property, out value))
return default(T);
return (T)value;
}
protected void Set<T>(T value, [CallerMemberName]string property = null)
{
_valueStore[property] = value;
OnPropertyChangedInternal(property);
}
protected void OnPropertyChanged([CallerMemberName]string property = null)
{
OnPropertyChangedInternal(property);
}
private void OnPropertyChangedInternal(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
公共抽象类BaseNotifyPropertyChanged:INotifyPropertyChanged
{
私有字典_valueStore=新字典();
公共事件属性更改事件处理程序属性更改;
受保护的T Get([CallerMemberName]字符串属性=null)
{
对象值=空;
if(!\u valueStore.TryGetValue(属性,输出值))
返回默认值(T);
返回(T)值;
}
受保护的无效集(T值,[CallerMemberName]字符串属性=null)
{
_valueStore[属性]=值;
不动产变更内部(不动产);
}
受保护的void OnPropertyChanged([CallerMemberName]字符串属性=null)
{
不动产变更内部(不动产);
}
私有void OnPropertyChangedInternal(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
然后从类中继承:
public class PlainOldObject : BaseNotifyPropertyChanged
{
public int MyProperty
{
get { return Get<int>(); }
set { Set(value); }
}
}
公共类PlainOldObject:BaseNotifyPropertyChanged
{
公共财产
{
获取{return get();}
集合{set(value);}
}
}
它为您提供后台存储和一切服务。如果属性实际发生了更改(比较引用或值),您可能希望添加逻辑以仅调用
OnPropertyChangedInternal
,但我将把它作为练习留给您。只需使用该类即可。您不需要创建DateTime
属性,而是创建一个observateObject
,然后只需绑定到DateClosed.Value
一些类就可以轻松更改,以实现INotifyPropertyChanged
。但是,由于您声明您有许多具有许多属性的类,因此手动或甚至使用模板来完成这项工作是一个真正的负担
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
你真正需要的是一个为你做这件事的工具,所以我向你展示了它的NotifyPropertyChanged插件。Fody所做的是在编译时在代码之间编织一些额外的代码。您只需在要实现的类上添加一个属性INotifyPropertyChanged
,其余的就完成了
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
正则表达式搜索和替换,T4模板,代码片段,您尝试过什么?我的意思是,你不是第一个遇到这种情况的人你对这个问题的评论正确吗?我不知道正则表达式和T4模板与这个lol有什么关系。我没有真正尝试过任何东西,因为除了setter之外,它似乎在其他任何地方调用PropertyChanged()。。但同时我不想只为getter和setters@user3653277是的,CodeCaster评论了正确的问题。T4模板允许生成C#代码,生成的代码由Visual Studio编译。正则表达式是生成C代码的一种可能的简单方法。当您使用
[CallerMemberName]时,可以删除可能重复的()=>SomeString
部分Set
方法中的
属性-它会导致编译器为您插入调用属性的名称。我看不出新属性如何比标准的full属性更好。你非常讨厌重复OnPropertyChanged()
(使用CallerMemberName
ofc)来换取这种语法?对他的问题,最简单的答案是:如果你想使用它,你需要在你的属性中实现INPC。但我的回答指出,通过这种特殊的方式实现它,不仅可以获得一些额外的好处,而且MVVMLIGHT还包含代码片段,使实现许多属性成为一种快照。字典查找而不是完整属性?代码片段会做得更好(避免您键入两行保存的代码)。@Sinatr我说这是一种方法,不是最佳方法,但即使有代码片段,以及一些性能问题,这也有一个优点,即具有触发通知的所有逻辑