System.Windows.Data Error: 19

Thought I’d brain dump a little problem I came across earlier today. Data Error 19.

Here’s the full error.

System.Windows.Data Error: 19 : Cannot convert ’40’ from type ‘Int32’ to type ‘System.Int64’ for ‘en-US’ culture with default conversions; consider using Converter property of Binding. NotSupportedException: ‘System.NotSupportedException: Int64Converter cannot convert from System.Int32.
   at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)’

How did I get here? Well, I have a bunch of generated values that come from a data dictionary , they’re generated into classes that contain Key/Value pairs, where the Key is an Int32.

This list is shown in a combo box, and the current value of the combo box is then bound to a CLR value type in a class. The only problem is that the classes CLR Type isn’t an Int32. It’s an Int64.

Now I know the the real fix is to generate a list of values for the combo box who’s type matches the destination bound value of Int64. The trouble is that I don’t always have that type information available. Thing is, I can’t remember any other control having the problem of changing types.

Heck,if you look at the conversion that it’s trying to do, it should be able to cope, converting an Int32 to an Int64 isn’t a narrowing cast, so there should be no problems with overflow. Eitherway, i just want to bind up this stuff and not worry about the types.

So, I wrote a small test app to verify what was going on.

boundVaueTest

Both the slider and the combo box are bound to an internal value, called surprisingly , "BoundValue" that’s declared as an Int64, and there’s a textbox that is then bound the "BoundValue" to show its current value.

 

I created a List<Int32> used as the ItemsSource for the ComboBox. – so the binding should set the BoundValue to an item in that list, or so I thought. Remember the BoundValue is an Int64, and the list the combo box is using is a list of Int32’s.

The slider is represented by a Double, so when you come to bind its value to the textbox the standard binding box only shows Double Properties – a gentle hint that binding it to an Int64 may not be the smartest thing to do.

BindinToMatchingTypes

So to show up the BoundValue variable we must change the "Show Matching Types Only" ComboBox to "Show All Properties". We can then bind the slider to our variable even though it’s an Int64, and the slider is a double.

Now we’re all bound up, we run the app, and slide the slider.

run1

As expected, the binding from the Slider (a Double) quite happily sets our Int64 variable, which the TextBox then duly displays. We run the app again, and this time we set the variable using the ComboBox.

run2

Not only does selecting one of the value not set our variable, if we check the output window of DevStudio we see the Databinding Error : 19.

debugout

So, the Slider will quite happily do an implicit type conversion between Double to the Int64 I have in my class, but the ComboBox’s binding won’t convert an Int32 to an Int64?

To fix this we need to create a ValueConverter to change the value’s type from Int32 to Int64, even though it seems that other controls perform this miracle without prompting!

As it turns out, there’s a handy function in the System.Convert namespace that helps up out here, making our Value converter very short and sweet.

public class TypeConverter : IValueConverter {
    public object Convert(object value, Type targetType,
                        object parameter, CultureInfo culture) {
        return System.Convert.ChangeType(value, targetType);
    }
    public object ConvertBack(object value, Type targetType,
                        object parameter, CultureInfo culture) {
        return System.Convert.ChangeType(value, targetType);
    }
}

An added bonus is that System.Convert.ChangeType will only throw exceptions when an overflow occurs on a narrowing cast. You can check this out with Lutz Roeders Reflector by digging into the System assembly.

Before we re-run we need to add the Converter to the applications resources so we can use it from Xaml.

Adding the following to the App.xaml makes the TypeConverter available within blend’s binding dialog.

<BindingExample:TypeConverter x:Key="TypeConverter"></BindingExample:TypeConverter>

and then we add the type converter to the binding using blend.

blendtypeconv

 

fixed

hey Presto, the combo box now sets the variable, and we’re free of the binding errors.

Code and solution below.

 

 

 

 

 

 

 

 

Download the Solution HERE

Technorati Tags: ,,,
This entry was posted in General. Bookmark the permalink.

Leave a Reply