Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use a WPF Dependency Property versus INotifyPropertyChanged

Do folks have any guidance on when a simple .NET property that fires INotifyPropertyChanged.PropertyChanged is sufficient in a view model? Then when do you want to move up to a full blown dependency property? Or are the DPs intended primarily for views?

like image 889
Keith Hill Avatar asked Aug 23 '10 19:08

Keith Hill


People also ask

When should I use dependency properties in WPF?

Dependency properties are used when you want data binding in a UserControl , and is the standard method of data binding for the WPF Framework controls. DPs have slightly better binding performance, and everything is provided to you when inside a UserControl to implement them.

Why do we use INotifyPropertyChanged?

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed. For example, consider a Person object with a property called FirstName .

What is attached property and dependency property in WPF?

In WPF, most UI-related attached properties on WPF types are implemented as dependency properties. WPF attached properties that are implemented as dependency properties support dependency property concepts, such as property metadata including default values from metadata.

How do you implement INotifyPropertyChanged?

To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.


1 Answers

There are a few approaches:

1. The dependency property

While you using the dependency property it makes the most sense in elements-classes that have a visual appearance (UIElements).

Pros:

  • WPF do the logic stuff for you
  • Some mechanism like animation use only dependency property
  • 'Fits' ViewModel style

Cons:

  • You need to derive form DependencyObject
  • A bit awkward for simple stuff

Sample:

public static class StoryBoardHelper {     public static DependencyObject GetTarget(Timeline timeline)     {         if (timeline == null)             throw new ArgumentNullException("timeline");          return timeline.GetValue(TargetProperty) as DependencyObject;     }      public static void SetTarget(Timeline timeline, DependencyObject value)     {         if (timeline == null)             throw new ArgumentNullException("timeline");          timeline.SetValue(TargetProperty, value);     }      public static readonly DependencyProperty TargetProperty =             DependencyProperty.RegisterAttached(                     "Target",                     typeof(DependencyObject),                     typeof(Timeline),                     new PropertyMetadata(null, OnTargetPropertyChanged));      private static void OnTargetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)     {         Storyboard.SetTarget(d as Timeline, e.NewValue as DependencyObject);     } } 

2. The System.ComponentModel.INotifyPropertyChanged

Usually, when creating a data object, you’ll use this approach. It is simple and neat solution for Data-like stuff.

Pros and Cons - complementary to 1. You need to to implement only one event (PropertyChanged).

Sample:

public class Student : INotifyPropertyChanged  {     public event PropertyChangedEventHandler PropertyChanged;     public void OnPropertyChanged(PropertyChangedEventArgs e)     {         if (PropertyChanged != null)            PropertyChanged(this, e);     }  }  private string name;  public string Name;  {      get { return name; }      set {             name = value;             OnPropertyChanged(new PropertyChangedEventArgs("Name"));          }  }  

3.PropertyNameChanged

Rising an event for each property with specified name(f.e. NameChanged). Event must have this name and it is up to you to handle/rise them. Similar approach as 2.

4. Get the binding

Using the FrameworkElement.GetBindingExpression() you can get the BindingExpression object and call BindingExpression.UpdateTarget() to refresh.

First and second are the most likely depending what is your goal.

All in all, it is Visual vs Data.

like image 70
Lukasz Madon Avatar answered Sep 30 '22 18:09

Lukasz Madon