Почему мой конвертер выдает неверную ошибку приведения? - PullRequest
7 голосов
/ 17 мая 2009

Я создал конвертер для преобразования из двойного в целое число.

Но строка "return (int) value;" всегда получает «указанное приведение неверно.»

Что мне нужно сделать, чтобы мой конвертер успешно преобразовал двойное число и отправил обратно целое число?

Преобразователь:

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>

Ответы [ 4 ]

8 голосов
/ 17 мая 2009

Вы пытаетесь привести (не конвертировать) из double в int, что не сработает. Вам нужно сделать неявное преобразование или использовать Convert.ToInt32 () - поскольку аргумент на самом деле имеет тип объекта, я думаю, вам понадобится последний, чтобы компилятор был доволен. Вам решать, хотите ли вы включить поставщика формата культуры или нет.

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

Вы можете использовать оператор приведения, когда объект имеет одинаковую форму , то есть когда один объект является экземпляром типа, к которому вы приводите. Например, если класс Foo расширяет класс Bar, то вы можете привести объект типа Foo к типу Bar - поскольку объект Foo имеет все методы и свойства, которые имел бы объект Bar. Однако вы не можете привести объект типа Bar к типу Foo, потому что Foo изменяет (или может изменить, поскольку это касается компилятора) форму Bar, добавляя методы или свойства, которые Барный объект не имеет.

В вашем случае вы имеете дело с примитивными типами, которые разделяют только интерфейс объекта - между ними нет отношений наследования, за исключением того, что они оба происходят от объекта. Однако между ними существует неявное преобразование . Вы можете назначить объект одного типа переменной другого, хотя вы можете потерять некоторую точность в значении.

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

Вы не можете, однако, привести объект одного типа к другому. Приведение подразумевает, что вы будете использовать объект, как если бы он был другого типа. В этом случае формы отличаются, и это невозможно сделать.

3 голосов
/ 17 мая 2009

Проблема заключается в том, что вы пытаетесь одновременно распаковать и снять с каста. Это не удастся. Сначала вы должны распаковать, а затем привести к соответствующему типу.

return (int)(double)value;

Эрик Липперт Недавно написал хорошую статью о том, почему это необходимо. Стоит прочитать

1 голос
/ 17 мая 2009

Вы хотите конвертировать, но вы делаете кастинг с двойного на int. Попробуйте это:

    public object Convert(object value, ...)
    {
        return (int)(double)value;
    }
1 голос
/ 17 мая 2009

Значение double заключено в объект внутри, и единственный способ получить его - это распаковать его как double. После этого вы можете разыграть его на int.

return (int)(double)value;

Вы также можете использовать метод Convert.ToInt32(object) (как предложил tvanfosson), который приведет объект к IConvertible и вызовет его виртуальный метод ToInt32, который в свою очередь вызовет метод Convert.ToInt32(double). Это, конечно, немного больше накладных расходов.

...