come passare un numero intero come ConverterParameter?


95

Sto cercando di collegarmi a una proprietà intera:

<RadioButton Content="None"
             IsChecked="{Binding MyProperty,
                         Converter={StaticResource IntToBoolConverter},
                         ConverterParameter=0}" />

e il mio convertitore è:

[ValueConversion(typeof(int), typeof(bool))]
public class IntToBoolConverter : IValueConverter
{
    public object Convert(object value, Type t, object parameter, CultureInfo culture)
    {
        return value.Equals(parameter);
    }

    public object ConvertBack(object value, Type t, object parameter, CultureInfo culture)
    {
        return value.Equals(false) ? DependencyProperty.UnsetValue : parameter;
    }
}

il problema è che quando viene chiamato il mio convertitore il parametro è stringa. ho bisogno che sia un numero intero. certo posso analizzare la stringa, ma devo farlo?

grazie per qualsiasi aiuto konstantin


2
Qualcuno sa come ottenerlo sulla piattaforma Windows Phone dove abbiamo una sintassi leggermente diversa per le associazioni? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} in questo esempio INT_VAL verrà passato come stringa
Krzysztof Kaczor

Risposte:


106

Ecco qua!

<RadioButton Content="None"
             xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <RadioButton.IsChecked>
        <Binding Path="MyProperty"
                 Converter="{StaticResource IntToBoolConverter}">
            <Binding.ConverterParameter>
                <sys:Int32>0</sys:Int32>
            </Binding.ConverterParameter>
        </Binding>
    </RadioButton.IsChecked>
</RadioButton>

Il trucco è includere lo spazio dei nomi per i tipi di sistema di base e quindi scrivere almeno l'associazione ConverterParameter in forma di elemento.


2
Questo non cambia il fatto che il tipo di IValueConverter.Convert()'s 'parametro' parametro è object. Devi ancora lanciarlo / analizzarlo ...
Dan J

6
@djacobson: vero, ma questo è ciò che l'attributo ValueConversion ti consente di specificare. Non sono esattamente sicuro se questo sia realmente utilizzato da in fase di compilazione o in fase di esecuzione. In termini della domanda dei poster originali, ha specificato che "ho bisogno che sia un numero intero. Ovviamente posso analizzare la stringa, ma devo?" Quindi la mia risposta allevia il fatto che non esiste l'analisi di una stringa ma solo l'unboxing di un numero intero che è ancora molto più sicuro.
jpierson

51

Per completezza, un'altra possibile soluzione (magari con meno battitura):

<Window
    xmlns:sys="clr-namespace:System;assembly=mscorlib" ...>
    <Window.Resources>
        <sys:Int32 x:Key="IntZero">0</sys:Int32>
    </Window.Resources>

    <RadioButton Content="None"
                 IsChecked="{Binding MyProperty,
                                     Converter={StaticResource IntToBoolConverter},
                                     ConverterParameter={StaticResource IntZero}}" />

(Ovviamente, Windowpuò essere sostituito con UserControle IntZeropuò essere definito più vicino al luogo di utilizzo effettivo.)


44

Non sono sicuro del motivo per cui le WPFpersone tendono a non essere inclini all'uso MarkupExtension. È la soluzione perfetta per molti problemi, incluso il problema menzionato qui.

public sealed class Int32Extension : MarkupExtension
{
    public Int32Extension(int value) { this.Value = value; }
    public int Value { get; set; }
    public override Object ProvideValue(IServiceProvider sp) { return Value; }
};

Se questa estensione di markup è disponibile nello XAMLspazio dei nomi "m", l'esempio del poster originale diventa:

<RadioButton Content="None"
             IsChecked="{Binding MyProperty,
                         Converter={StaticResource IntToBoolConverter},
                         ConverterParameter={m:Int32 0}}" />

Questo funziona perché il parser dell'estensione di markup può vedere il tipo forte dell'argomento del costruttore e convertirlo di conseguenza, mentre l'argomento ConverterParameter di Binding è (meno informativo) di tipo Object.


Grazie, è stato utile. Sarà la mia prima estensione XAML. Ma penso che sia meglio fare Valueun objectpiuttosto che int, evitare di inscatolarlo ogni volta ProvideValue. (E poi, privateevita di assegnare direttamente qualcosa di illegale).
Zeus

1
@Zeus In genere ProvideValueviene chiamato solo una volta per istanza di estensione di markup, quindi il boxing dovrebbe comunque verificarsi solo una volta. Non facendolo nel costruttore, evito del tutto il pugilato se ProvideValuenon viene mai chiamato. Per quanto riguarda la creazione di Valueprivato, ciò precluderebbe l'utilizzo dell'estensione di markup nella XAMLsintassi dell'elemento oggetto: msdn.microsoft.com/en-us/library/…
Glenn Slayden

Il tuo ultimo paragrafo è sbagliato. Si chiama conversione del tipo e si applica anche alle proprietà. Il fatto è che Binding.ConverterParameternon ha un tipo specifico (è solo un object) quindi il parser non sa quale conversione applicare, quindi ogni letterale viene trattato come una stringa.
HB

(Quindi, se l'estensione avesse un costruttore predefinito, {m:Int32 Value=0}funzionerebbe altrettanto bene.)
HB

5

Non usare value.Equals. Uso:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)

8
Perché non vuoi usare value.Equals?
Zack

1

Sarebbe bello esprimere in qualche modo le informazioni sul tipo per ConverterValue in XAML, ma non penso sia possibile al momento. Quindi immagino che tu debba analizzare l'oggetto Converter nel tuo tipo previsto con una logica personalizzata. Non vedo un altro modo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.