user3688491
user3688491

Reputation: 167

NotifyOnPropertyChange realization

How can I implement NotifyOnPropertyChange method? To call it from the inheritors ViewModelBase could be as:

NotifyOnPropertyChange (() => Property) 

The input to this method is applied lambda expression that specifies a property of change which need to notify.

Upvotes: 1

Views: 265

Answers (3)

Bartosz Wójtowicz
Bartosz Wójtowicz

Reputation: 1401

You can use NotificationObject from Prism library. It's already implemented there as RaisePropertyChanged<T>

Here're links to the source code for the NotificationObject and for the PropertySupport classes.

Upvotes: 0

Bartosz W&#243;jtowicz
Bartosz W&#243;jtowicz

Reputation: 1401

Your implementation can look like this. It's implemented using System.Linq.Expressions namespace.

        protected void RaisePropertyChanged<T>(System.Linq.Expressions.Expression<Func<T>> lambda)
        {
            dynamic l = lambda.Body;
            string propertyName = l.Member.Name;
            OnPropertyChanged(propertyName);
        }

Here's an example of the whole class.

    public class NotificationObject : INotifyPropertyChanged
    {
        private string _someProperty;

        public string SomeProperty
        {
            get { return _someProperty; }
            set
            {
                _country = value;
                RaisePropertyChanged(() => SomeProperty);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }



        protected void RaisePropertyChanged<T>(System.Linq.Expressions.Expression<Func<T>> lambda)
        {
            dynamic l = lambda.Body;
            string propertyName = l.Member.Name;
            OnPropertyChanged(propertyName);
        }
    }

The full blown implementation without using dynamic would look like this:

        protected void RaisePropertyChanged<T>(System.Linq.Expressions.Expression<Func<T>> lambda)
        {
            if (lambda == null) throw new ArgumentNullException("lambda");

            var memberExpression = lambda.Body as MemberExpression;
            if (memberExpression == null) throw new ArgumentException("Invalid lambda expression.","lambda");

            var property = memberExpression.Member as PropertyInfo;
            if (property == null) throw new ArgumentException("Invalid lambda expression. Expression must be a property.", "lambda");

            // check if the property is not static
            var getMethod = property.GetGetMethod(true);
            if (getMethod.IsStatic) throw new ArgumentException("Invalid lambda expression. Property cannot be static.", "propertyExpression");

            string propertyName = memberExpression.Member.Name;
            OnPropertyChanged(propertyName);
        }

Upvotes: 1

Nathan A
Nathan A

Reputation: 11319

You can implement it like this so you don't have to give the property name at all (as long as it's called directly from the property setter). This way, there is no fear of renaming properties or typos.

private void NotifyOnPropertyChanged([CallerMemberName] string caller = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(caller));
    }
}

Then, implement your property like so:

string _somePropertyValue;

string SomeProperty
{
    get { return _somePropertyValue; }
    set 
    { 
        if(_somePropertyValue != value)
        {
            _somePropertyValue = value;
            NotifyOnPropertyChanged();
        }
    }
}

Upvotes: 2

Related Questions