Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my converter giving an invalid cast error?

I created a Converter to convert from double to integer.

But the line "return (int)value;" always gets a "specified cast is not valid."

What do I have to do so that my Converter successfully converts a double and sends back an integer?

Converter:

namespace TestChangeAngle
{
    [ValueConversion(typeof(double), typeof(int))]
    class DoubleToIntegerConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (int)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

XAML:

<Page x:Class="TestChangeAngle.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestChangeAngle"
    Title="Page1">
    <Page.Resources>
        <local:DoubleToIntegerConverter x:Key="DoubleToIntegerConverter"/>
    </Page.Resources>

    <StackPanel HorizontalAlignment="Left" Margin="20">
        <Image Source="images\logo2.png" 
               RenderTransformOrigin="0.5, 0.5"
               Width="100" 
               Margin="10">
            <Image.RenderTransform>
                <RotateTransform Angle="{Binding ElementName=TheSlider, Path=Value}"/>
            </Image.RenderTransform>
        </Image>
        <Slider x:Name="TheSlider"
                Width="200" 
                Minimum="0"
                Maximum="360"
                HorizontalAlignment="Center"
                Margin="10" 
                Cursor="Hand"/>
        <TextBox x:Name="TheAngle"
                 Margin="10"
                 Width="100">
            <TextBox.Text>
                <Binding ElementName="TheSlider"
                         Path="Value"
                         UpdateSourceTrigger="PropertyChanged"
                         Converter="{StaticResource DoubleToIntegerConverter}"
                         Mode="TwoWay">
                    <Binding.ValidationRules>
                        <local:MinMaxValidationRule Minimum="0" Maximum="360"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

    </StackPanel>
</Page>
like image 936
Edward Tanguay Avatar asked May 17 '09 13:05

Edward Tanguay


3 Answers

You are attempting to cast (not convert) from double to int, which won't work. You need to do an implicit conversion or use Convert.ToInt32() -- since the argument is actually of type object I think you'll need the latter to keep the compiler happy. It's up to you whether you want to include the culture's format provider or not.

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    return Convert.ToInt32(value);
}

You can use the cast operator when the object's have the same shape, that is, when one object is an instance of the type to which you are casting. For example, if class Foo extends class Bar, then you can cast an object of type Foo to type Bar - because a Foo object has all the methods and properties that a Bar object would. You couldn't, however, cast an object of type Bar to type Foo because Foo changes (or can change, as far as the compiler is concerned) the shape of Bar, by adding methods or properties that a Bar object doesn't have.

In your case you are dealing with primitive types which only share the object interface - there isn't an inheritance relationship between them except that they both derive from object. There is, however, an implicit conversion between the two. You can assign an object one type to a variable of the other, though you may lose some precision in the value.

double x = 1.1;
int y = 0;

y = x;  // implicit conversion, this works, y will be 1
x = y;  // implicit conversion, this works, x will be 1.0

You can't, however, cast an object of one type to the other. Casting implies that you will be using the object as if it were of the other type. In this case the shapes differ and it can't be done.

like image 182
tvanfosson Avatar answered Nov 14 '22 12:11

tvanfosson


The problem is that you are attempting to do both an unbox and a cast at the same time. This will fail. You must first unbox and then cast to the appropriate type.

return (int)(double)value;

Eric Lippert Recently wrote a nice article on exactly why this is necessary. It's worth the read

  • http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
like image 3
JaredPar Avatar answered Nov 14 '22 13:11

JaredPar


The double value is boxed inside an object, and the only way to get it out is to unbox it as a double. After that you can cast it to an int.

return (int)(double)value;

You can also use the Convert.ToInt32(object) method (as tvanfosson suggested), which will cast the object to IConvertible and call it's virtual ToInt32 method, which in turn will call the Convert.ToInt32(double) method. That is of course a bit more overhead.

like image 1
Guffa Avatar answered Nov 14 '22 14:11

Guffa