Reputation: 647
I have this class:
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; }
}
}
And the derive class:
public class MyFile : MyFileInfo
{
}
So every time my _bytesSent
has changed i want to notify:
public event PropertyChangedEventHandler PropertyChanged;
public virtual void NotifyPropertyChange(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
Using this:
public static int PropertyName
{
get { return _propertyName; }
set
{
_totalPacketsSent = value;
NotifyPropertyChange("...");
}
}
So my question is: where should i declare this event ? in the base class on the one that derive
Upvotes: 0
Views: 825
Reputation: 1
It probably wouldn't hurt to have a base class that accumulates some useful operations associated with INotifyPropertyChanged
. I usually use something akin to the following:
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
}
The calls are styled to allow you to do most things in one line thus:
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value); }
}
or
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value, "PropertyName", "AdditionalRelatedPropertyName"); }
}
or
public int PropertyName
{
get { return _propertyName; }
set { ChangeAndNotify(ref _propertyName, value, () => SomeActionOnSuccess()); }
}
Upvotes: 0
Reputation: 1626
The base class, it should work normally. One more thing, change your method to this:
public virtual void NotifyPropertyChange([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
}
This way, you can call it without specifying the property name like so:
NotifyPropertyChange ();
The compiler will fill the property name for you. You can still specify the property:
NotifyPropertyChange ("Property");
NotifyPropertyChange (nameof (Property));
As it was said by Liero, you should use the standard naming OnPropertyChanged scheme. Note: The ? (Safe navigation operator) and nameof is only available in C# 6.
Then everytime you want a property to notify the UI that it got changed, you do:
public String MyTestProperty
{
get {return _MyTestProperty;}
set {
_MyTestProperty = value;
NotifyPropertyChange ();
}
}
Upvotes: 0
Reputation: 27350
by convention, you should define it in the base class as protected virtual with name "OnEventName":
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
Upvotes: 2