This is part 3 in a series I’m writing about a WPF User Control I’ve created and posted up on CodePlex. In this installment, I’m going to be talking about creating dependency properties, in the DateRangeSlider, I used them to enable/disable the upper and lower sliders independently for dealing with the maximum, minimum, upper and lower values.
First of all, a little bit about dependency properties. A dependency property is a type of property introduced with WPF that solves many problems in WPF around styling, data binding, animation, and more. As I’ve been working with WPF, I’ve noticed that one of the primary features of a dependency property used is its built-in ability to provide change notification. If you start diving into MVVM, you might start asking yourself why do I need a dependency property instead of a property that utilizes the INotifyPropertyChanged implementation? That is when the styling and animating come into play, because you can only style and animate dependency properties.
If you look through the code at CodePlex, you’ll see I have dependency properties for the slider’s minimum, maximum, upper value, lower value, enabling the lower slider, enabling the upper slider, and finally locking the lower and upper values to the minimum and maximum respectively. We’ll take a look at the Minimum property.
I want to start with Line 8 below, because this is where the real definition of the MinimumProperty is located. It is a public static field and by convention, has a Property suffix. Depedency properties are created using the DependencyProperty.Register method which at the minimum takes needs the name of the dependency property to register (“Minimum”) and the type of the property (typeof(DateTime)) and the type of the owner (typeof(DateRangeSlider)) that is registering the dependency property. The overload of Register I used also includes a PropertyMetadata argument where I defined a default value and a callback method.
Line 2 starts the basic property definition. with your get and set methods that call the methods GetValue and SetValue which are inherited by System.Windows.DependencyObject. Each dependency property you make will look almost identical to this because there is no guarantee that your getter or setter will be called directly, WPF will usually call the GetValue and SetValue methods directly, bypassing any custom logic you might feel compelled to add.
The last thing you’ll find in the snippet below is the callback method. If you need custom logic to be run when your property is changed, you’ll want to use an overload of the DependencyProperty.Register method that lets to define a callback method in the PropertyMetadata argument. In my example, I’m using the callback to check if the LowerValue should be locked to the Minimum or if the LowerValue is less than the new Minimum and adjusting it accordingly. One last thing to note here, is that our callback is static, which means it isn’t connected to a particular instance. The instance we want to work with is inside the argument DependencyObject d and we must first cast it out.
Dependency Property – Minimum
- #region Dependency Property – Minimum
- public DateTime Minimum
- {
- get { return (DateTime)GetValue(MinimumProperty); }
- set { SetValue(MinimumProperty, value); }
- }
-
- public static readonly DependencyProperty MinimumProperty =
- DependencyProperty.Register("Minimum", typeof(DateTime), typeof(DateRangeSlider), new UIPropertyMetadata(DateTime.Now.AddDays(-15), new PropertyChangedCallback(OnMinimumChanged)));
-
- public static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- DateRangeSlider slider = (DateRangeSlider)d;
-
- if (slider.IsLowerValueLockedToMin || slider.LowerValue < (DateTime)e.NewValue)
- {
- slider.LowerValue = (DateTime)e.NewValue;
- }
- }
-
- #endregion
Hopefully, this helps explain dependency properties to anyone looking for it, I’ve never claimed to be a great writer (or even a mediocre one). If I missed anything or if you have questions, let me know.