Sometimes when setting properties with XAML you may get the AG_E_PARSER_BAD_PROPERTY_VALUE error. This can mean a variety of things, but in this post we are going to visit a situation where .NET cannot convert the XAML string to the .NET object's type.
A good example of this is a Date property. Let's say we have a control that has a MaxDate property. If we set the property in XAML it may look like this: MaxDate="01-01-2009". Unfortunately this does not work. You'll get our fatal parser error because the parser is not smart enough to parse the string to a date type.
The workaround is to hold .NET parsers hand and tell it how to parse the string to our desired type (in this case a Date). We'll do this by first creating our own TypeConverter. I'll call it the DateTypeConverter. We'll inherit from the TypeConverter base class and override key methods used to detect if we can convert from/to a type and handle the actual conversion process. Here's our TypeConverter class for converting from and to a Date type.
1: Imports System.ComponentModel
2:
3: Public Class DateTypeConverter
4: Inherits TypeConverter
5:
6: Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
7: If sourceType.Equals(GetType(String)) Then
8: Return True
9: Else
10: Return MyBase.CanConvertFrom(context, sourceType)
11: End If
12: End Function
13:
14: Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
15: If destinationType.Equals(GetType(String)) Then
16: Return True
17: Else
18: Return MyBase.CanConvertTo(context, destinationType)
19: End If
20: End Function
21:
22: Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
23: If TypeOf value Is String Then
24: Try
25: Return Date.Parse(value.ToString())
26: Catch
27: Throw New InvalidCastException(value)
28: End Try
29: Else
30: Return MyBase.ConvertFrom(context, culture, value)
31: End If
32: End Function
33:
34: Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
35: If destinationType.Equals(GetType(String)) Then
36: Return value.ToString()
37: Else
38: Return MyBase.ConvertTo(context, culture, value, destinationType)
39: End If
40: End Function
41: End Class
Now that we have our custom converter created, we need to tell our control's property to use this converter when being set via a property attribute. In our case, when the parser attempts to set the property, it will invoke our DateTypeConverter and parse the string to a date properly.
1: Public Shared ReadOnly MaxDateProperty As DependencyProperty = DependencyProperty.Register("MaxDate", GetType(Date), GetType(SilverlightControl1), New PropertyMetadata(Date.MaxValue, AddressOf MaxDateChangedHandler))
2:
3: <TypeConverter(GetType(DateTypeConverter))> _
4: Public Property MaxDate() As Date
5: Get
6: Return DirectCast(GetValue(SilverlightControl1.MaxDateProperty), Date)
7: End Get
8: Set(ByVal value As Date)
9: SetValue(SilverlightControl1.MaxDateProperty, value)
10: End Set
11: End Property
Take note of line 3. Adding the TypeConverter attribute tells the .NET XAML parser to use our DateTypeConverter to parse the String to Date.
SiverlightDateTime_Soln.zip (593.57 kb)