¿Cómo pasar un número entero como ConverterParameter?

95

Estoy tratando de vincularme a una propiedad entera:

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

y mi convertidor es:

[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;
    }
}

el problema es que cuando se llama a mi convertidor, el parámetro es una cadena. Necesito que sea un número entero. por supuesto que puedo analizar la cadena, pero ¿tengo que hacerlo?

gracias por cualquier ayuda konstantin

Akonsu
fuente
2
¿Alguien sabe cómo lograr esto en la plataforma de Windows Phone donde tenemos una sintaxis ligeramente diferente para los enlaces? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} en este ejemplo, INT_VAL se pasará como una cadena
Krzysztof Kaczor

Respuestas:

106

¡Aqui tienes!

<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>

El truco consiste en incluir el espacio de nombres para los tipos de sistemas básicos y luego escribir al menos el enlace ConverterParameter en forma de elemento.

jpierson
fuente
2
Esto no cambia el hecho de que el tipo de IValueConverter.Convert()'s 'parámetro' parámetro es object. Todavía tienes que emitirlo / analizarlo ...
Dan J
6
@djacobson: verdadero, pero eso es lo que el atributo ValueConversion le permite especificar. No estoy seguro de si realmente lo usa en tiempo de compilación o en tiempo de ejecución. En cuanto a la pregunta sobre los carteles originales, especificó que "necesito que sea un número entero. Por supuesto que puedo analizar la cadena, pero ¿tengo que hacerlo?" Entonces, mi respuesta alivia eso, ya que no hay análisis de una cadena, sino solo unboxing de un número entero, que aún es mucho más seguro.
jpierson
51

Para completar, una posible solución más (quizás con menos escritura):

<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}}" />

(Por supuesto, Windowse puede reemplazar por UserControly IntZerose puede definir más cerca del lugar de uso real).

Vlad
fuente
44

No estoy seguro de por qué la WPFgente tiende a no estar dispuesta a consumir MarkupExtension. Es la solución perfecta para muchos problemas, incluido el mencionado aquí.

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; }
};

Si esta extensión de marcado está disponible en el XAMLespacio de nombres 'm', el ejemplo del póster original se convierte en:

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

Esto funciona porque el analizador de extensiones de marcado puede ver el tipo fuerte del argumento del constructor y convertir en consecuencia, mientras que el argumento ConverterParameter de Binding es (menos informativo) de tipo Objeto.

Glenn Slayden
fuente
Gracias, eso fue útil. Será mi primera extensión XAML. Pero creo que es mejor hacer Valueun en objectlugar de intevitar meterlo en cajas cada vez ProvideValue. (Y luego, privateevite asignar algo ilegal directamente).
Zeus
1
@Zeus Por ProvideValuelo general, solo se llama una vez por instancia de extensión de marcado, por lo que el encuadre solo debe ocurrir una vez de todos modos. Al no hacerlo en el constructor, evito boxear por completo si ProvideValuenunca se llama. En cuanto a hacer Valueprivado, esto excluiría el uso de la extensión de marcado en la XAMLsintaxis del elemento de objeto: msdn.microsoft.com/en-us/library/…
Glenn Slayden
Tu último párrafo está mal. Se llama conversión de tipos y también se aplica a las propiedades. El caso es que Binding.ConverterParameterno tiene un tipo específico (es solo un object), por lo que el analizador no sabe qué conversión aplicar, por lo tanto, cada literal se trata como una cadena.
HB
(Entonces, si su extensión tuviera un constructor predeterminado, entonces {m:Int32 Value=0}funcionaría igual de bien.)
HB
5

No lo use value.Equals. Utilizar:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
fuente
8
¿Por qué no quieres usar value.Equals?
Zack
1

Sería bueno expresar de alguna manera la información de tipo para ConverterValue en XAML, pero no creo que sea posible a partir de ahora. Así que supongo que tienes que analizar el objeto convertidor a tu tipo esperado por alguna lógica personalizada. No veo otra forma.

SKG
fuente