When to use a WPF Dependency Property versus INotifyPropertyChanged

16,031

Solution 1

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.

Solution 2

As far as I know, DependencyProperty is only required when you need

  1. PropertyValue inheritence
  2. you need to allow the property to be set in Style setters
  3. Use animation for the property

etc.

These features will not be available with normal properties.

Solution 3

DependencyProperty is required if you want to allow a binding to be set on the property. Usually this is for custom UIElements you create. You want to allow people to be able to bind data to your UIElements.

<local:MyUIElement MyProperty={Binding Path=SomethingToBindTo} />

To do this requires that MyProperty is a dependancy property

Solution 4

The main problem I see with INotifyPropertyChanged is if you viewmodel is complex containing many nested types it appears that you have to bubble the PropertyChanged event up through the hierarchy.

Solution 5

As the other answers have already said enough about when to create dependency property. i.e.

  1. PropertyValue inheritence
  2. you need to use binding on a property
  3. Use animation for the property

The one more perspective/question on this is "In a WPF application is makes sense to create dependency properties in a control cause they are likely to change during user interaction like Height,width, text,content, background etc but what about other classes like Behaviors Classes(Non UI classes). Do properties in those classes need to be a dependency property?"

I won't say for very absolute or emphasis on some set of rules here but you should create your properties as DP. As from design perspective if a property is DP it's always in default form of WPF to use/bind.i.e.

  1. As a DP is much more fast/natural in reflecting changes compare to a normal CLR property.
  2. A DP has validation mechanism to validate the value assigned and a default structure to revert the value.
  3. A DP has Coerce value callback to control the limits of property.
  4. A DP has meta data associated with it unlike CLR property.

In terms of practices I've seen people doing many mistakes in nested bindings and then raising changes these kind of faults doesn't happen with a DP cause of it's design and compatibility of raising change itself. So with a little extra syntax you put a flexibility/performance/ easeness to your application. So go for it wherever affordable.

Still can't say sure for ViewModel classes/other helper classes. will update the answer if found convincing reasons in future.

Just a post worth reading on this topic

Share:
16,031
Keith Hill
Author by

Keith Hill

I am a software architect specializing in .NET Technologies. I am also a former Windows PowerShell MVP.

Updated on June 07, 2022

Comments

  • Keith Hill
    Keith Hill about 2 years

    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?

  • Keith Hill
    Keith Hill over 13 years
    This is a great answer and deserves more up votes! I'd vote twice if I could. :-)
  • Admin
    Admin about 5 years
    This is actually the correct answer. You only need a DependencyProperty if you want the property to be the target of a binding. Other than that you can get by with a standard property plus INotifyPropertyChanged if you need it.
  • Daniel Möller
    Daniel Möller about 4 years
    I'm pretty sure I did this a many times with INotifyPropertyChanged, is there any "hidden aspect" that is not clear in your answer?