jak przekazać liczbę całkowitą jako parametr ConverterParameter?

95

Próbuję powiązać z właściwością całkowitą:

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

a mój konwerter to:

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

problem polega na tym, że gdy wywoływany jest mój konwerter, parametrem jest łańcuch. potrzebuję, żeby to była liczba całkowita. oczywiście mogę przeanalizować ciąg, ale czy muszę?

dzięki za jakąkolwiek pomoc konstantin

akonsu
źródło
2
Czy ktoś wie, jak to osiągnąć na platformie Windows Phone, gdzie mamy nieco inną składnię powiązań? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} w tym przykładzie INT_VAL zostanie przekazany jako ciąg
Krzysztof Kaczor

Odpowiedzi:

107

Proszę bardzo!

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

Sztuczka polega na tym, aby uwzględnić przestrzeń nazw dla podstawowych typów systemu, a następnie napisać przynajmniej powiązanie ConverterParameter w postaci elementu.

jpierson
źródło
2
To nie zmienia faktu, że typ IValueConverter.Convert()„s «parametru» parametr jest object. Nadal musisz to przesłać / przeanalizować ...
Dan J,
6
@djacobson - True, ale to właśnie pozwala na określenie atrybutu ValueConversion. Nie jestem do końca pewien, czy jest to naprawdę używane w czasie kompilacji czy w czasie wykonywania. Jeśli chodzi o pytanie dotyczące oryginalnych plakatów, sprecyzował, że „potrzebuję, aby była to liczba całkowita. Oczywiście mogę przeanalizować ciąg, ale czy muszę?” Moja odpowiedź łagodzi więc to, że nie ma parsowania łańcucha, a jedynie rozpakowywanie liczby całkowitej, która jest nadal znacznie bezpieczniejsza.
jpierson,
51

Dla kompletności jeszcze jedno możliwe rozwiązanie (być może z mniejszą liczbą wpisywania):

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

(Oczywiście Windowmożna go zastąpić UserControli IntZerozdefiniować bliżej miejsca rzeczywistego użytkowania).

Vlad
źródło
45

Nie wiem, dlaczego WPFludzie nie chcą używać MarkupExtension. Jest to idealne rozwiązanie wielu problemów, w tym wspomnianej tutaj kwestii.

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

Jeśli to rozszerzenie znaczników jest dostępne w XAMLprzestrzeni nazw `` m '', przykład oryginalnego postera wygląda następująco :

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

Działa to, ponieważ parser rozszerzenia znaczników może zobaczyć silny typ argumentu konstruktora i odpowiednio przekonwertować, podczas gdy argument ConverterParameter Binding jest (mniej informacyjnie) typem obiektowym.

Glenn Slayden
źródło
Dzięki, to było przydatne. To będzie moje pierwsze rozszerzenie XAML. Ale myślę, że lepiej, aby zamiast , aby uniknąć boks to za każdym razem w . (A potem postaraj się uniknąć bezpośredniego przypisywania czegoś nielegalnego). ValueobjectintProvideValueprivate
Zeus,
1
@Zeus Zwykle ProvideValuejest wywoływana tylko raz na wystąpienie rozszerzenia znaczników, więc i tak pole powinno wystąpić tylko raz. Nie robiąc tego w konstruktorze, całkowicie unikam boksu, jeśli ProvideValuenigdy nie jest wywoływany. Jeśli chodzi o ustawienie Valueprywatne, wykluczałoby to użycie rozszerzenia znaczników w XAMLskładni elementu obiektu: msdn.microsoft.com/en-us/library/…
Glenn Slayden
Twój ostatni akapit jest zły. Nazywa się to konwersją typów i dotyczy również właściwości. Chodzi o to, że Binding.ConverterParameternie ma określonego typu (jest to po prostu object), więc parser nie wie, jaką konwersję zastosować, stąd każdy literał jest traktowany jako ciąg.
HB
(Więc jeśli twoje rozszerzenie miało domyślny konstruktor, {m:Int32 Value=0}działałoby równie dobrze.)
HB
4

Nie używaj value.Equals. Posługiwać się:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
źródło
8
Dlaczego nie chcesz użyć value.Equals?
Zack
0

Byłoby miło w jakiś sposób wyrazić informacje o typie dla wartości ConverterValue w XAML, ale nie sądzę, aby było to obecnie możliwe. Więc myślę, że musisz przeanalizować obiekt konwertera do oczekiwanego typu za pomocą niestandardowej logiki. Nie widzę innego sposobu.

SKG
źródło