Errata: WPF Recipes in C# 2008 4-3. Add Properties to a User Control
I am an avid reader. We can always learn something new in reading a new book. But no book can be perfect, esp. technical books on new technologies. So I would take notes when I noticed some inaccurate, misgudied or incorrect discussions or examples. And starting from this year, I will share some notes in my blog.
In WPF Recipes in C# 2008, chapter 4, example 3: Add Properties to a User Control, it demostrates how to use DependencyProperty to interact with a custom PageNumberControl. PageNumberControl defines two Dependency Properties: Current and Total. And the definition for Total looks like this:
public int Total
{
get
{
return (int) GetValue(TotalProperty);
}
set
{
if(value >= Current
&& value >= 0)
{
SetValue(TotalProperty, value);
}
}
}
public static readonly DependencyProperty TotalProperty =
DependencyProperty.Register("Total",
typeof(int),
typeof(PageNumberControl),
new PropertyMetadata(0));
In CLR property Total setter, the code above does some sanity check: (1) Total value should not be negative. (2) Total value should not be smaller than Current value. Such constraint makes sense, but we should not place the check in CLR property setter.
That is because CLR property should always be a thin wrapper of the underlying Dependency Property. Users can always set TotalProperty to any int value with such code pageNumberControl1.SetValue(PageNumberControl.TotalProperty, -100); and the CLR property setter is not involved at all.
What's more, WPF features such as data binding, style and animations work on Dependency Property, rather than CLR property.
The fix is to use ValidValueCallback (for "Total value should not be negative number") and CoerceValueCallback (for "Total value should not be smaller than Current value") when we register DependencyProperty.
The same applies to Current property.
(This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm)