Wpf INotifyPropertyChanged与派生类
我有这门课:Wpf INotifyPropertyChanged与派生类,wpf,inotifypropertychanged,Wpf,Inotifypropertychanged,我有这门课: public class MyFileInfo : INotifyPropertyChanged { private string _file; private int _bytesSent; public MyFileInfo(string file) { } public string File { get { return _file; } set { _file = value;
public class MyFileInfo : INotifyPropertyChanged
{
private string _file;
private int _bytesSent;
public MyFileInfo(string file)
{
}
public string File
{
get { return _file; }
set { _file = value; }
}
public int BytesSent
{
get { return _bytesSent; }
set { _bytesSent= value; }
}
}
和派生类:
public class MyFile : MyFileInfo
{
}
因此,每次我的\u bytesSent
发生更改时,我都要通知:
public event PropertyChangedEventHandler PropertyChanged;
public virtual void NotifyPropertyChange(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
使用此选项:
public static int PropertyName
{
get { return _propertyName; }
set
{
_totalPacketsSent = value;
NotifyPropertyChange("...");
}
}
所以我的问题是:我应该在哪里宣布这个事件?在派生基类的基类上,它应该正常工作。还有一件事,将您的方法更改为:
public virtual void NotifyPropertyChange([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
}
这样,您就可以在不指定属性名称的情况下调用它,如下所示:
NotifyPropertyChange ();
编译器将为您填写属性名称。您仍然可以指定属性:
NotifyPropertyChange ("Property");
NotifyPropertyChange (nameof (Property));
正如Liero所说,您应该使用标准的命名OnPropertyChanged方案。
注:是什么?(安全导航操作员)和名称仅在C#6中可用
然后,每当您希望某个属性通知UI它已更改时,您都会执行以下操作:
public String MyTestProperty
{
get {return _MyTestProperty;}
set {
_MyTestProperty = value;
NotifyPropertyChange ();
}
}
按照惯例,您应该在基类中将其定义为名为“OnEventName”的受保护虚拟机:
如果有一个基类来积累一些与
INotifyPropertyChanged
相关联的有用操作,可能不会有什么坏处。我通常使用类似于以下内容的内容:
public class NotifiableBase : INotifyPropertyChanged
{
#region Utility methods
/// <summary>
/// Notify of a property change and optional additional dependencies.
/// </summary>
public void Notify([CallerMemberName] string propertyName = null, params string[] additionalNames)
{
OnPropertyChanged(propertyName);
foreach (var name in additionalNames)
{
OnPropertyChanged(name);
}
}
/// <summary>
/// Makes a change to the supplied reference if different.
/// If different, notify of a property change and optional additional dependencies.
/// </summary>
public bool ChangeAndNotify<T>(ref T toChange, T newValue, [CallerMemberName] string propertyName = null, params string[] additionalNames)
{
var cmp = EqualityComparer<T>.Default;
if (cmp.Equals(toChange, newValue) == false)
{
toChange = newValue;
OnPropertyChanged(propertyName);
foreach (var name in additionalNames)
{
OnPropertyChanged(name);
}
return true;
}
return false;
}
/// <summary>
/// Makes a change to the supplied reference if different.
/// If different, notify of a property change and optional additional dependencies then call action.
/// </summary>
public bool ChangeAndNotifyWithAction<T>(ref T toChange, T newValue, Action action, [CallerMemberName] string propertyName = null, params string[] additionalNames)
{
var ret = ChangeAndNotify(ref toChange, newValue, propertyName, additionalNames);
if (ret)
{
action();
}
return ret;
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
或
或
我没有否决,但在本例中,
CallerMemberName
不是最佳选择,因为他想通知TotalPacketsSent
属性已从PropertyName
属性更改,因此您必须指定参数。是的,我不是暗示是您,我甚至不知道有新的答案,所以我认为这个人正在寻找它,一定是一个肇事逃逸的XD,但我只是忘记了派生类正在做工作,并且这个类中的属性正在更改,所以我认为它应该在派生类中。我说的对吗?如果您正在更改MyProperty=Value之类的属性,它应该可以正常工作,因为您正在属性的Set方法内调用NotifyPropertyChange,所有要发出通知的属性都必须在其值更改后调用此方法。例如,BytesSent属性,如果在_bytesSent=value之后将集合更改为调用NotifyPropertyChange,它将通知UI bytesSent已更改。这篇文章比较老,所以没有使用后来发布的C#功能。使用表达式也是表示属性(,)的方便方法。
public class NotifiableBase : INotifyPropertyChanged
{
#region Utility methods
/// <summary>
/// Notify of a property change and optional additional dependencies.
/// </summary>
public void Notify([CallerMemberName] string propertyName = null, params string[] additionalNames)
{
OnPropertyChanged(propertyName);
foreach (var name in additionalNames)
{
OnPropertyChanged(name);
}
}
/// <summary>
/// Makes a change to the supplied reference if different.
/// If different, notify of a property change and optional additional dependencies.
/// </summary>
public bool ChangeAndNotify<T>(ref T toChange, T newValue, [CallerMemberName] string propertyName = null, params string[] additionalNames)
{
var cmp = EqualityComparer<T>.Default;
if (cmp.Equals(toChange, newValue) == false)
{
toChange = newValue;
OnPropertyChanged(propertyName);
foreach (var name in additionalNames)
{
OnPropertyChanged(name);
}
return true;
}
return false;
}
/// <summary>
/// Makes a change to the supplied reference if different.
/// If different, notify of a property change and optional additional dependencies then call action.
/// </summary>
public bool ChangeAndNotifyWithAction<T>(ref T toChange, T newValue, Action action, [CallerMemberName] string propertyName = null, params string[] additionalNames)
{
var ret = ChangeAndNotify(ref toChange, newValue, propertyName, additionalNames);
if (ret)
{
action();
}
return ret;
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value); }
}
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value, "PropertyName", "AdditionalRelatedPropertyName"); }
}
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value, () => SomeActionOnSuccess()); }
}