Reputation: 25959
this question might look a little trivial, but it might not be. I'm just wondering which of the following two cases is better for indirect property notification, or perhaps there is an even better way.
The scenario:
I have two properties, the first one is an object called HoldingObject, the second one is a boolean called IsHoldingObject, which is false if HoldingObject == null, otherwise it's true. I'm just wondering what is the best notification mechanism for IsHoldingObject:
Case (A) - Notify IsHoldingObject changed from the HoldingObject proeperty:
public class NotifyingClass1 : INotifyPropertyChanged
{
private object _holdingObject;
public object HoldingObject
{
get { return _holdingObject; }
set
{
if (_holdingObject != value)
{
_holdingObject = value;
NotifyPropertyChanged("HoldingObject");
// Notify from the property that is being checked
NotifyPropertyChanged("IsHoldingObject");
}
}
}
public bool IsHoldingObject { get { return this.HoldingObject == null; } }
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Case (B) - Notify IsHoldingObject changed from the IsHoldingObject directly, by setting it to false or true from HoldingObject property:
public class NotifyingClass2 : INotifyPropertyChanged
{
private object _holdingObject;
public object HoldingObject
{
get { return _holdingObject; }
set
{
if (_holdingObject != value)
{
_holdingObject = value;
NotifyPropertyChanged("HoldingObject");
// 1) Set the property here
this.IsHoldingObject = _holdingObject != null;
}
}
}
private bool _isHoldingObject;
public bool IsHoldingObject
{
get { return _isHoldingObject; }
set
{
if (_isHoldingObject != value)
{
_isHoldingObject = value;
// 2) Notify directly from the property
NotifyPropertyChanged("IsHoldingObject");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
I personally lean to the first one because it requires less code, but I'm not sure how recommendable it is to do that. Let me know if there is another (better) way.
Thanks!
Upvotes: 2
Views: 202
Reputation: 34840
In most scenarios it does not matter. Lets look at the options
So I guess it comes down to what ever is more readable for you. I prefer "Calculating each time". Then using this http://code.google.com/p/notifypropertyweaver/ it allows me to write this code
public class NotifyingClass1 : INotifyPropertyChanged
{
public object HoldingObject { get; set; }
public bool IsHoldingObject { get { return HoldingObject == null; } }
public event PropertyChangedEventHandler PropertyChanged;
}
And have this compiled to the assembly (ie the dependency is derived)
public class NotifyingClass1 : INotifyPropertyChanged
{
private object holdingObject;
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public object HoldingObject
{
get { return holdingObject; }
set
{
if (holdingObject !=value)
{
holdingObject = value;
OnPropertyChanged("HoldingObject");
OnPropertyChanged("IsHoldingObject");
}
}
}
public bool IsHoldingObject { get { return (HoldingObject == null); } }
}
Upvotes: 1
Reputation: 30498
I almost always go for the second one. That way, all the code responsible for setting a given property is in one place. In this particular case, the IsHoldingObject property is entirely dependent on the HoldingObject property, so it may not apply. But in general, it may be less code now, but what happens if you need to update that property from somewhere else later on?
The pain you are having (the verbosity of the code) can be easily mitigated by a helper method that is used to set properties in a view model (this can live in a base class):
protected bool SetValue<T>(ref T field, T value, string propertyName)
{
if (!Equals(field, value))
{
field = value;
NotifyPropertyChanged(propertyName);
return true;
}
return false;
}
Your properties then become:
private object _holdingObject;
public object HoldingObject
{
get { return _holdingObject; }
set
{
if (SetValue(ref _holdingObject, value, "HoldingObject"))
this.IsHoldingObject = _holdingObject != null;
}
}
private bool _isHoldingObject;
public bool IsHoldingObject
{
get { return _isHoldingObject; }
private set { SetValue(ref _isHoldingObject, value, "IsHoldingObject"); }
}
Upvotes: 1
Reputation: 4865
interesting idea. I think, I would have used the BindingConverter approach, which convertes HoldingObject to the value you like.
I'm curious about other opinions.
Regards
Upvotes: 0