There is an exception which many people hit when first creating dependency properties.
System.Windows.Markup.XamlParseException: The invocation of the constructor on type ‘[type name here]’ that matches the specified binding constraints threw an exception.
Don’t worry – it’s very easy to fix and also very commonly made.
You first dependency property may look something like this, especially if you use the code snippet “propdp“.
public long MyProperty { get { return (long)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } } public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register( "MyProperty", typeof(long), typeof(MyClass), new PropertyMetadata(0));
If you created your code using the code snippet it will compile just fine and the world will be a happy place. The problem lies in the constructor of the PropertyMetadata on line 12 above where you set the default value for the property.
The definition of the constructor is:
public PropertyMetadata(object defaultValue);
The type of the parameter ‘defaultValue‘ is ‘object‘, this means that your default value will be boxed as an object type.
The error comes when the default value is needed and is unboxed. If you didn’t carefully force the type of the value going in then the most sensible type will be chosen by the compiler, which may differ from the type you specified on line 10, i.e. the underlying type you wish to use for your dependency property.
Using the above as an example, the default value is set to ‘0‘ – the compiler will interpret ‘0‘ to be an Int32 and then the constructor will store that Int32 typed value as the default value in the defaultValue object.
When you come to need the default value the code that is executed behind the scenes will attempt to turn your default value back to the type specified for your dependency property, i.e.
long value = (long)defaultValue;
Much to many people’s surprise, this is not possible and will throw the exception above. Why? Well, you need to unbox back to the underlying type before you cast it to another type.
Take the following code, which you can paste into a console project to check out:
var myInt = 0; Console.WriteLine(myInt.GetType().Name); // produces Int32 object myObj = myInt; Console.WriteLine(myObj.GetType().Name); // produces Int32 - the underlying type // no problem long myLong1 = (long)myInt; // no problem - unboxing to int and then casting to long long myLong2 = (long)(int)myObj; // exception - can't unbox to a different type long myLong3 = (long)myObj;
Note that on line 1 I declared the variable using var instead of int, however we can still see that the compiler has decided that Int32 is the best way to go with this value.
So, back to the exception, and how to correct it. Simple really, make sure that the compiler is aware of the type of value that you are passing in and make sure that it matches the type you are declaring for your dependency property.
In the example above we only need to replace line 12 with the following using an explicit cast.
new PropertyMetadata((long)0));
Alternatively we could have used a type suffixes as a shortcut.
new PropertyMetadata(0l));
Other type suffices are:
u – uint
l – long
ul – ulong
f – float
d – double
m – decimal
If you are interested in a more depth article on boxing and unboxing and casting in general, see Eric Lippert’s excellent blog post.