WPF: Tips - Dependency Property Default Double Trouble
This tip explains how to resolve the "Default value type does not match type of property ..... " error.
Scenario
Since double is a common type for control properties double is also a very common type for custom dependency properties the developer adds. The scenario this article addresses is:
You are adding a Double type Dependency Property to your class, and you use the default snippet to generate some boiler plate code for you.
Typing "propdp" then tab, you generate a stub and change the default int type to double.
You end up with some code along these lines:
public double MyProperty
{
get { return (double)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(double), typeof(ownerclass), new PropertyMetadata(0));
Once you fix up the name of your class and give your property a nice meaningful name... time to consider if anything else needs doing.
That default of zero from "PropertyMetadata(0)" looks good so let's set it in some markup and spin her up.
When you do, the window takes a suspiciously long time to show up.
Just as you're thinking "Oh dear... that doesn't look good".
You see an error:
Default value type does not match type of property 'MyProperty'
Well actually, it's some generic xaml error you see initially and you have to dig into the Inner Exception to see that a type difference is somehow to blame.
Not good!
Reason for the Error
The reason you get that error is partly because there is no intelligence in the Visual Studio snippets. That zero is just a sort of a marker really and whilst it kind of looks like a zero, it's the wrong type of zero.
Wait - you can have the wrong type of zero?
Absolutely!
If you take a look at DependencyProperty.Register you will see that PropertyMetadata parameter is System.Windows.PropertyMetadata if you then in turn look that PropertyMetadata up, you will see it has overloaded constructors:
- PropertyMetadata()
- PropertyMetadata(Object)
- PropertyMetadata(PropertyChangedCallback)
- PropertyMetadata(Object, PropertyChangedCallback)
- PropertyMetadata(Object, PropertyChangedCallback, CoerceValueCallback)
Carefully looking at that, the generated code passes one parameter so that's option 2) and it's passed in as an object.
Because it's passed as an object that means that zero gets boxed up. It's the nitty gritty of how boxing works that is important here. The zero is turned into a value type and from there "boxed" into an object. In the process of turning it into a value type .Net needs to decide exactly what value type it will be and so it infers it from the number. That 0 is interpreted as being an integer.
If you change the type of the dependency property to int, then your error would go away. Well, at least that error would. Of course you might have some other issues.
You probably had a good reason to make it a double in the first place.
Resolving the Error
You can tell it to hand in that zero explicitly as a double by using 0.0 or 0D instead of 0:
public double MyProperty
{
get { return (double)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(double), typeof(WindowExtender), new PropertyMetadata(0D));
Either approach will work.
If you frequently use double dependency properties you might consider changing that propdp snippet using the approach described in this article.
See Also
WPF Portal
This is part of a series of WPF Tips articles.