views:

33

answers:

2

Hello, 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!

A: 

Hi,

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

DHN
+1  A: 

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"); }
}
Abe Heidebrecht
+1 This is exactly how I do it.
rossisdead