Suggestion: NotifyPropertyChanged Method

Jul 16, 2010 at 8:27 PM

Can you add the following to the INotifyPropertyChanged section of the ViewModelBase.  The code allows you to signal property changed events using lambda exprestion

        /// Notify using a lambda expresion
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        protected void NotifyPropertyChanged<T>(Expression<Func<T>> property)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;
            if (propertyInfo == null)
            {
                throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
            }

            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyInfo.Name));
        }
Then in a setter of a property you can do this:

NotifyPropertyChanged(() => PatronSearchResult);

Coordinator
Jul 19, 2010 at 12:52 PM
Edited Jul 19, 2010 at 12:58 PM

CInch already has this, and it uses a better idea that this (not that your idea is bad). As in your example above you are effectively building an Expression Tree every time a property changes, which you then evaluate. What CInch does is to rely on a shared PropertyChangedEventArgs which was found using an Expression tree, have a look at this code from CInch

 

 

static PropertyChangedEventArgs viewsArgs =
            ObservableHelper.CreateArgs<ViewModelBase>(x => x.Views);

        public ObservableCollection<WorkspaceData> Views
        {
            get { return views; }
            set
            {
                views = value;
                NotifyPropertyChanged(viewsArgs);
            }
        }

Which makes use of this code (again from Cinch)



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;

namespace Cinch
{
    /// <summary>
    /// A small helper class that has a method to help create
    /// PropertyChangedEventArgs when using the INotifyPropertyChanged
    /// interface
    /// </summary>
    public static class ObservableHelper
    {
        #region Public Methods
        /// <summary>
        /// Creates PropertyChangedEventArgs
        /// </summary>
        /// <param name="propertyExpression">Expression to make 
        /// PropertyChangedEventArgs out of</param>
        /// <returns>PropertyChangedEventArgs</returns>
        public static PropertyChangedEventArgs CreateArgs<T>(
            Expression<Func<T, Object>> propertyExpression)
        {
            return new PropertyChangedEventArgs(
                GetPropertyName<T>(propertyExpression));
        }

        /// <summary>
        /// Creates PropertyChangedEventArgs
        /// </summary>
        /// <param name="propertyExpression">Expression to make 
        /// PropertyChangedEventArgs out of</param>
        /// <returns>PropertyChangedEventArgs</returns>
        public static string GetPropertyName<T>(
            Expression<Func<T, Object>> propertyExpression)
        {
            var lambda = propertyExpression as LambdaExpression;
            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = lambda.Body as UnaryExpression;
                memberExpression = unaryExpression.Operand as MemberExpression;
            }
            else
            {
                memberExpression = lambda.Body as MemberExpression;
            }

            var propertyInfo = memberExpression.Member as PropertyInfo;

            return propertyInfo.Name;
        }

        #endregion
    }
}

See how it is static so only declared once per type, not per instance, and you do not have to evaluate the Expression tree every time, as you already did it once, and that is all you need to do.

 

Oh and one more thing, by using this ObservableHelper class, you can do this from any INPC class not just one that inherits from ViewModelBase