INotifyPropertyChange

By now almost all of you that have been confronted with the MVVM pattern have also seen the importance of the INotifyPropertyChange interface for the View Model. However, regardless of where it gets used one cannot escape it components of the name “Interface Notify Property Changed”. Let’s have a closer look at an example to see where all this is leading:

        /// <summary>
        /// The <see cref="MyProperty" /> property's name.
        /// </summary>
        public const string MyPropertyPropertyName = "MyProperty";

        private bool m_myProperty = false;

        /// <summary>
        /// Gets or sets a value indicating whether my property has been set.
        /// </summary>
        /// <value><c>true</c> if has been set; otherwise, <c>false</c>.</value>
        public bool MyProperty
        {
            get
            {
                return m_myProperty;
            }

            set
            {
                if (m_myProperty == value)
                {
                    return;
                }

                m_myProperty = value;
                RaisePropertyChanged(MyPropertyPropertyName);
            }
        }

As we all know we have to implement the event and have some way to execute it. Hence the “NotifyPropertyChange” method appears in the code. Regardless whether this method removes the need for the “magic string” or not it should get executed only when the property changes, i.e. the setter is called as seen above.

So, what is the problem? Everything is clear. We know all this.

Okay.

So, how many of you have seen this type of code, or maybe have written something similar?

        /// <summary>
        /// The <see cref="PropertyWithSideEffect" /> property's name.
        /// </summary>
        public const string PropertyWithSideEffectPropertyName = "PropertyWithSideEffect";

        private bool _myPropertyWithSideEffect = false;

        /// <summary>
        /// Gets or sets a value indicating whether property with side effect has changed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if the property with side effect has changed; otherwise, <c>false</c>.
        /// </value>
        public bool PropertyWithSideEffect
        {
            get
            {
                return _myPropertyWithSideEffect;
            }

            set
            {
                if (_myPropertyWithSideEffect == value)
                {
                    return;
                }

                _myPropertyWithSideEffect = value;
                DoSomeRatherLongProcessing();
                GetSomethingFromTheDatebase();
                RaisePropertyChanged(PropertyWithSideEffectPropertyName);
            }
        }

Now maybe someone out there can tell me why I need to call methods from within a setter? I see none. However the property now has a really bad side effect associated with it.

What about when I cannot be bothered to set another non-associated property? Now what property/properties has/have changed? I see only one but two have been notified.

        /// <summary>
        /// The <see cref="PropertyWithBadRaisePropertyChanged" /> property's name.
        /// </summary>
        public const string PropertyWithBadRaisePropertyChangedPropertyName = "PropertyWithBadRaisePropertyChanged";

        private bool _myProperty = false;

        /// <summary>
        /// Gets or sets a value indicating whether the property with bad raise property changed has changed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if property with bad raise property changed has changed; otherwise, <c>false</c>.
        /// </value>
        public bool PropertyWithBadRaisePropertyChanged
        {
            get
            {
                return _myProperty;
            }

            set
            {
                if (_myProperty == value)
                {
                    return;
                }

                _myProperty = value;
                RaisePropertyChanged(PropertyWithBadRaisePropertyChangedPropertyName);
                RaisePropertyChanged(MyPropertyPropertyName);
            }
        }

This misuse is almost unforgivable as it tells the system to rebind to a property that has not changed. Even more unforgivable is the misuse inside the property itself where not only the property change event is raise for the property but also another one appears raising the property change event for another property. This is a very unwanted side-effect for the GUI designer/developer.

If you want that the raise the event that notifies everyone that your property has changed then you can just change the property itself. If the property does not need to be changed then do not raise the property changed event.

So either the developer does not know correct usage or is too lazy to code properly – whichever way you look at it the code is ugly and incorrect. Since the property changed is an event there is nothing stopping the developer listening and handling this event as well. Of course, there is the overhead of maintaining those “magic string” or LINQ expressions. I know this does not get rid of the urge to raise property changed events, but it does reduce the raising non-related property change events within the property setter.

So the next time you feel the need to raise the property change event in another place in the code just set the property correctly though it setter.

That’s all folks…

Advertisements

~ by Intelligence4 on October 8, 2011.

 
%d bloggers like this: