Skip to content

PropertyChangedBase

bereal75 edited this page Feb 10, 2021 · 14 revisions

PropertyChangedBase is base class for types implementing INotifyPropertyChanged, and provides methods for raising PropertyChanged notifications.

Raising Notifications

There are a number of ways to raise PropertyChanged notifications, depending on what exactly you want to do.

The most common case is having a property raise a notification each time it's assigned to. PropertyChangedBase provides a nice utility method to help: SetAndNotify. It takes, by reference, a field, and a value to assign to the field. If the field's value != the value, the assignment happens, and a PropertyChanged notification is raised. For example:

class MyClass : PropertyChangedBase
{
   private string _name;
   public string Name
   {
      get { return this._name; }
      set { SetAndNotify(ref this._name, value); }
   }

To connect to the object you have to put in the view:

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>

If you want to raise a PropertyChanged notification for a property other than the current one, there are a few ways of achieving that, too (depending on whether you're using C#6, or below). The preferred C# 6 way is to use nameof(), as that is very cheap and provides compile-time safety. If you're using C# 5 or below, you can use an expression: this is slower, but also gives compile-time safety. If you really want, you can use a raw string as well. See below:

class MyClass : PropertyChangedBase
{
   private string _firstName;
   public string FirstName
   {
      get { return _firstName; }
      private set
      {
         SetAndNotify(ref _firstName, value);

         // Preferred if you're using C# 6, as it provides compile-time safety
         this.NotifyOfPropertyChange(nameof(this.FullName));         
      }
   }

   private string _lastName;
   public string LastName
   {
      get { return _lastName; }
      private set
      {
         SetAndNotify(ref _lastName, value);

         // Preferred for C# 5 and below, as it provides compile-time safety
         this.NotifyOfPropertyChange(() => this.FullName);
      }
   }

   public string FullName
   {
      get { return FirstName + " " + LastName; }
   }
}

You can also wire things together in the constructor, like this:

class MyClass : PropertyChangedBase
{
   private string _firstName, _lastName;

   public MyClass()
   {
      this.Bind(s => s.FirstName, (o, e) => NotifyOfPropertyChange(nameof(FullName)));
      this.Bind(s => s.LastName, (o, e) => NotifyOfPropertyChange(nameof(FullName)));
   }

   public string FirstName
   {
      get { return _firstName; }
      private set { SetAndNotify(ref _firstName, value); }
   }

   public string LastName
   {
      get { return _lastName; }
      private set { SetAndNotify(ref _lastName, value); }
   }

   public string FullName
   {
      get { return FirstName + " " + LastName; }
   }
}

Dispatching Events

By default, PropertyChanged events are raised on the current thread (and WPF takes care of dispatching them to the UI thread). If you do want to change this, however, you can! PropertyChangedBase has a property called PropertyChangedDispatcher, which has an Action<Action>, and defaults to Execute.DefaultPropertyChangedDispatcher (which you can assign) (which has the value a => a()).

If you want to change this to execute on the UI thread, you can do the following.

To change for all instances of PropertyChangedBase:

class Bootstrapper : Bootstrapper<MyRootViewModel>
{
   public override void Configure()
   {
      base.Configure();
      Execute.DefaultPropertyChangedDispatcher = Execute.OnUIThread;
   }
}

To change for just once instance of PropertyChangedBase:

class MyClass : PropertyChangedBase
{
   public MyClass()
   {
      this.PropertyChangedDispatcher = Execute.OnUIThread;
   }
}

Use with PropertyChanged.Fody

PropertyChanged.Fody is a fantastic package, which injects code at compile-time to automatically raise PropertyChanged notifications for your properties, allowing you to write very concise code. It will also figure out dependencies between your properties and raise notifications appropriately for example:

class MyClass : PropertyChangedBase
{
   public string FirstName { get; private set; }
   public string LastName { get; private set; }
   public string FullName { get { return String.Format("{0} {1}", this.FirstName, this.LastName); } }

   public void SomeMethod()
   {
      // PropertyChanged notifications are automatically raised for both FirstName and FullName
      this.FirstName = "Fred";
   }

PropertyChangedBase also takes care to integrate with Fody.PropertyChanged. Notifications raised by Fody.PropertyChanged are raised using the PropertyChangedDispatcher.

Therefore you do not need to do anything special in order to use Fody.PropertyChanged with any subclass of Screen, ValidatingModelBase, or PropertyChangedBase.

Clone this wiki locally