In the previous article, we explored how to create custom type instances in XAML. In this article, let's take a look at Dependency Properties (DPs) - the foundational concept that powers bindings, styles, animations, property inheritance, and templates in WPF.
đź§ What is a Dependency Property?
A Dependency Property is a property managed by the WPF property system.
Instead of storing values in a private field, WPF keeps them in a centralized property store that evaluates the effective value by combining multiple sources:
- Local values (including
{Binding}and values set viaSetValue— the method used to assign values to DPs in code) - Styles & templates (setters, triggers)
- Value inheritance (e.g.,
FontSizeflowing down the visual tree) - Default values from metadata
- Animations
- Coercion and validation hooks
Think of DPs as “properties with superpowers” that participate in every layer of the WPF pipeline.
âť“ Why not just CLR properties?
Plain C# properties:
- ❌ Don’t support XAML
{Binding}on controls - ❌ Can’t be styled, animated, or inherited
- ❌ Don’t trigger layout or visual updates automatically
- ❌ Aren’t recognized by the WPF property system
DPs provide:
- âś… Binding, styling, templating, and animation
- âś… Default values via metadata
- âś… Automatic layout invalidation (
AffectsMeasure,AffectsArrange,AffectsRender) - âś… Built-in change notifications
- âś… Value coercion & validation
🎬 Watch the Demo
Here’s a basic example of how to define a Dependency Property in a custom control
⚖️ How WPF decides the final value
When multiple inputs exist, WPF determines the final value based on precedence:
- Animations (if active)
- Local value (including
{Binding}andSetValue) - Template/Style triggers and setters
- Inherited value (from parent)
- Default value (from property metadata)
Coercion can adjust the chosen value to stay within a valid range.
🎯 TL;DR
- Use a Dependency Property if it needs to participate in binding, styles, templates, animations, default values, or property inheritance.
- Use a CLR property + INotifyPropertyChanged for ViewModels.
- DPs only exist on classes derived from
DependencyObject(likeFrameworkElementorControl).
Here’s the source code used in the demo:
đź§± Project Setup
DependencyPropertyDemo/
├── DependencyPropertyDemo.csproj
├── App.xaml
├── MainWindow.xaml
└── MainWindow.xaml.cs
đź’» MainWindow.xaml.cs
namespace DependencyPropertyDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public int MyValue
{
get { return (int)GetValue(MyValueProperty); }
set { SetValue(MyValueProperty, value); }
}
// Using a DependencyProperty as the backing store for Age. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyValueProperty =
DependencyProperty.Register("Age", typeof(int), typeof(MainWindow), new PropertyMetadata(25));
private void Button_Click(object sender, RoutedEventArgs e)
{
MyValue++;
}
}
}
🪄 MainWindow.xaml
Here we add a Person object directly inside a Label.
<Window x:Class="DependencyPropertyDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DependencyPropertyDemo"
mc:Ignorable="d"
Title="MainWindow"
Height="300"
Width="300"
FontSize="30">
<StackPanel Orientation="Vertical"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Button Content="Click Me"
Click="Button_Click"
FontSize="16"
Width="100"
Height="30"
Margin="10" />
<TextBlock x:Name="myTextBlock"
Text="{Binding MyValue}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="{Binding MyValue}"
Margin="10" />
</StackPanel>
</Window>