Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现INotifyPropertyChanged时的属性获取程序和设置程序?_C#_.net_Winforms_Inotifypropertychanged - Fatal编程技术网

C# 实现INotifyPropertyChanged时的属性获取程序和设置程序?

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

我试图为许多类实现INotifyPropertyChanged,这些类中的每一个都有很多属性。我一直在关注如何实现INofifyPropertyChanged,但它们的指令在类具有许多属性的情况下似乎并不实用

目前,我的大多数酒店都使用速记:

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);
    }
}
这为您提供了一些简洁的功能:

  • 强命名(与示例中的魔术字符串不同)
  • Set
    仅在值不同时触发INPC事件
  • 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我说这是一种方法,不是最佳方法,但即使有代码片段,以及一些性能问题,这也有一个优点,即具有触发通知的所有逻辑