2009-05-17 12 views
7

Ho creato un convertitore per convertire da doppio a intero.Perché il mio convertitore genera un errore di trasmissione non valido?

Ma la riga "restituisce (int) valore;" ottiene sempre un "cast specificato non valido".

Cosa devo fare in modo che il mio convertitore converta correttamente un doppio e restituisca un intero?

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> 

risposta

8

Si sta tentando di lanciare (non convertire) dal doppio a int, che non funziona. È necessario eseguire una conversione implicita o utilizzare Convert.ToInt32() - poiché l'argomento è in realtà di tipo oggetto, penso che sarà necessario quest'ultimo per mantenere il compilatore felice. Spetta a te decidere se includere o meno il fornitore di formati della cultura.

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

È possibile utilizzare l'operatore di cast quando l'oggetto sono la stessa forma , cioè quando un oggetto è un'istanza del tipo a cui si sta casting. Ad esempio, se la classe Foo estende la classe Bar, puoi lanciare un oggetto di tipo Foo per digitare Bar - perché un oggetto Foo ha tutti i metodi e le proprietà che farebbe un oggetto Bar. Tuttavia, non è possibile lanciare un oggetto di tipo Bar per digitare Foo perché Foo cambia (o può cambiare, per quanto riguarda il compilatore) la forma di Bar, aggiungendo metodi o proprietà che un oggetto Bar non esegue Ho.

Nel tuo caso hai a che fare con tipi primitivi che condividono solo l'interfaccia dell'oggetto - non esiste una relazione di ereditarietà, tranne che entrambi derivano dall'oggetto. Esiste tuttavia una conversione implicita tra i due. È possibile assegnare a un oggetto un tipo a una variabile dell'altro, sebbene si possa perdere una certa precisione nel valore.

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 

Tuttavia, non è possibile trasmettere un oggetto di un tipo all'altro. La trasmissione implica che utilizzerai l'oggetto come se fosse dell'altro tipo. In questo caso le forme differiscono e non possono essere eseguite.

+0

Se il parametro è sempre un valore doppio di ritorno (int) (doppio); funzionerà anche, ma ToInt32 è migliore. – Nir

+0

@Nir - sì, questo consentirebbe al compilatore di eseguire una conversione implicita da double a int anche se sembra un cast. – tvanfosson

1

Il valore double è inscatolato all'interno di un oggetto, e l'unico modo per farlo fuori è di unboxing come double. Dopo di che puoi lanciarlo su un int.

return (int)(double)value; 

È inoltre possibile utilizzare il metodo Convert.ToInt32(object) (come tvanfosson suggerito), che sarà il cast dell'oggetto al IConvertible e chiamare è ToInt32 metodo virtuale, che a sua volta chiama il metodo Convert.ToInt32(double). Questo è ovviamente un po 'più alto.

1

Si desidera convertire ma si sta eseguendo il cast da doppio a int. Prova questo:

public object Convert(object value, ...) 
    { 
     return (int)(double)value; 
    }