como passar um inteiro como ConverterParameter?

95

Estou tentando vincular a uma propriedade inteira:

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

e meu conversor é:

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

o problema é que quando meu conversor é chamado o parâmetro é string. eu preciso que seja um número inteiro. claro que posso analisar a string, mas é necessário?

obrigado por qualquer ajuda konstantin

Akonsu
fonte
2
Alguém sabe como conseguir isso na plataforma Windows Phone, onde temos uma sintaxe ligeiramente diferente para ligações? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} neste exemplo INT_VAL será passado como uma string
Krzysztof Kaczor

Respostas:

106

Aqui está!

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

O truque é incluir o namespace para os tipos básicos de sistema e, em seguida, escrever pelo menos a vinculação ConverterParameter na forma de elemento.

jpierson
fonte
2
Isso não muda o fato de que o tipo de IValueConverter.Convert()'s 'parâmetro' parâmetro é object. Você ainda tem que lançar / analisar ...
Dan J
6
@djacobson - Verdadeiro, mas é isso que o atributo ValueConversion permite que você especifique. Não tenho certeza se isso é realmente usado em tempo de compilação ou em tempo de execução. Em termos da pergunta dos pôsteres originais, ele especificou que "preciso que seja um número inteiro. Claro que posso analisar a string, mas preciso?" Portanto, minha resposta alivia que não há análise de uma string, mas apenas o desempacotamento de um inteiro, o que é ainda muito mais seguro.
jpierson
51

Para completar, mais uma solução possível (talvez com menos digitação):

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

(Claro, Windowpode ser substituído por UserControle IntZeropode ser definido mais próximo do local de uso real.)

Vlad
fonte
44

Não sei por que as WPFpessoas tendem a não querer usar MarkupExtension. É a solução perfeita para muitos problemas, incluindo o problema mencionado aqui.

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 esta extensão de marcação estiver disponível no XAMLnamespace 'm', o exemplo do autor da postagem original será:

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

Isso funciona porque o analisador de extensão de marcação pode ver o tipo forte do argumento do construtor e converter de acordo, enquanto o argumento ConverterParameter de Binding é (menos informativamente) do tipo objeto.

Glenn Slayden
fonte
Obrigado, isso foi útil. Será minha primeira extensão XAML. Mas eu acho que é melhor fazer Valueuma objectvez de int, para evitar boxe-lo cada vez em ProvideValue. (E então, privateevite atribuir algo ilegal diretamente).
Zeus
1
@Zeus Normalmente ProvideValueé chamado apenas uma vez por instância de extensão de marcação, portanto, o boxing deve ocorrer apenas uma vez. Ao não fazer isso no construtor, evito o boxe completamente se ProvideValuenunca for chamado. Quanto a tornar Valueprivado, isso impediria o uso da extensão de marcação na XAMLsintaxe do elemento de objeto: msdn.microsoft.com/en-us/library/…
Glenn Slayden
Seu último parágrafo está errado. É chamado de conversão de tipo e também se aplica a propriedades. O fato é que Binding.ConverterParameternão tem um tipo específico (é apenas um object), então o analisador não sabe qual conversão aplicar, portanto, todo literal é tratado apenas como uma string.
HB
(Portanto, se sua extensão tivesse um construtor padrão, {m:Int32 Value=0}funcionaria da mesma forma.)
HB
5

Não use value.Equals. Usar:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
fonte
8
Por que você não quer usar value.Equals?
Zack
1

Seria bom expressar de alguma forma as informações de tipo para o ConverterValue em XAML, mas não acho que seja possível no momento. Então eu acho que você tem que analisar o objeto Converter para o seu tipo esperado por alguma lógica personalizada. Não vejo outra maneira.

SKG
fonte