comment passer un entier comme ConverterParameter?

95

J'essaye de me lier à une propriété entière:

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

et mon convertisseur est:

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

le problème est que lorsque mon convertisseur est appelé, le paramètre est une chaîne. j'ai besoin que ce soit un entier. bien sûr, je peux analyser la chaîne, mais dois-je le faire?

merci pour toute aide konstantin

Akonsu
la source
2
Est-ce que quelqu'un sait comment y parvenir sur la plate-forme Windows Phone où nous avons une syntaxe légèrement différente pour les liaisons? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} dans cet exemple INT_VAL sera passé sous forme de chaîne
Krzysztof Kaczor

Réponses:

106

Et voilà!

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

L'astuce consiste à inclure l'espace de noms pour les types de système de base, puis à écrire au moins la liaison ConverterParameter sous forme d'élément.

jpierson
la source
2
Cela ne change pas le fait que le type de IValueConverter.Convert()de » « paramètre » paramètre est object. Vous devez encore le lancer / analyser ...
Dan J
6
@djacobson - Vrai mais c'est ce que l'attribut ValueConversion vous permet de spécifier. Je ne sais pas exactement si cela est vraiment utilisé au moment de la compilation ou au moment de l'exécution. En ce qui concerne la question originale des affiches, il a précisé que "j'ai besoin que ce soit un entier. Bien sûr, je peux analyser la chaîne, mais dois-je le faire?" Donc ma réponse atténue cela en ce sens qu'il n'y a pas d'analyse d'une chaîne mais seulement le déballage d'un entier, ce qui est encore beaucoup plus sûr.
jpierson
51

Pour être complet, une autre solution possible (peut-être avec moins de frappe):

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

(Bien sûr, Windowpeut être remplacé par UserControl, et IntZeropeut être défini plus près du lieu d'utilisation réel.)

Vlad
la source
44

Je ne sais pas pourquoi les WPFgens ont tendance à être peu enclins à utiliser MarkupExtension. C'est la solution parfaite pour de nombreux problèmes, y compris le problème mentionné ici.

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 cette extension de balisage est disponible dans l' XAMLespace de noms 'm', alors l'exemple de l'affiche d'origine devient:

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

Cela fonctionne parce que l'analyseur d'extension de balisage peut voir le type fort de l'argument du constructeur et effectuer la conversion en conséquence, tandis que l'argument ConverterParameter de Binding est (de manière moins informative) de type Object.

Glenn Slayden
la source
Merci, c'était utile. Ce sera ma première extension XAML. Mais je pense qu'il vaut mieux faire Valueun objectplutôt que int, éviter de le boxer à chaque fois ProvideValue. (Et puis, faites-le privatepour éviter d'attribuer directement quelque chose d'illégal).
Zeus
1
@Zeus En général, il ProvideValuen'est appelé qu'une seule fois par instance d'extension de balisage, de sorte que l'encadrement ne devrait se produire qu'une seule fois de toute façon. En ne le faisant pas dans le constructeur, j'évite complètement la boxe si elle ProvideValuen'est jamais appelée. Quant à rendre Valueprivé, cela empêcherait d'utiliser l'extension de balisage dans la XAMLsyntaxe des éléments d'objet: msdn.microsoft.com/en-us/library
Glenn Slayden
Votre dernier paragraphe est faux. Cela s'appelle la conversion de type et s'applique également aux propriétés. Le fait est qu'il Binding.ConverterParametern'a pas de type spécifique (c'est juste un object) donc l'analyseur ne sait pas quelle conversion appliquer, donc chaque littéral est simplement traité comme une chaîne.
HB
(Donc, si votre extension avait un constructeur par défaut, {m:Int32 Value=0}cela fonctionnerait tout aussi bien.)
HB
5

N'utilisez pas value.Equals. Utilisation:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
la source
8
Pourquoi tu ne veux pas utiliser value.Equals?
Zack
1

Ce serait bien d'exprimer les informations de type pour le ConverterValue en XAML, mais je ne pense pas que ce soit possible pour le moment. Donc, je suppose que vous devez analyser l'objet Converter selon votre type attendu par une logique personnalisée. Je ne vois pas d'autre moyen.

SKG
la source