как передать целое число как ConverterParameter?


95

Я пытаюсь выполнить привязку к целочисленному свойству:

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

и мой конвертер:

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

проблема в том, что когда мой конвертер вызывается, параметром является строка. мне нужно, чтобы это было целое число. Конечно, я могу разобрать строку, но нужно ли?

спасибо за любую помощь Константин


2
Кто-нибудь знает, как добиться этого на платформе Windows Phone, где у нас немного другой синтаксис для привязок? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} в этом примере INT_VAL будет передан как строка
Krzysztof Kaczor

Ответы:


106

Вот так!

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

Уловка состоит в том, чтобы включить пространство имен для основных типов системы, а затем записать хотя бы привязку ConverterParameter в форме элемента.


2
Это не меняет тот факт , что тип IValueConverter.Convert()«S „параметр“ параметра есть object. Вам все еще нужно разыграть / проанализировать его ...
Дэн Дж

6
@djacobson - Истина, но это то, что позволяет указать атрибут ValueConversion. Не совсем уверен, действительно ли это используется во время компиляции или во время выполнения. Что касается первоначального вопроса плаката, он уточнил, что «мне нужно, чтобы это было целое число. Конечно, я могу разобрать строку, но должен ли я?» Таким образом, мой ответ смягчает то, что в нем нет синтаксического анализа строки, а только распаковка целого числа, что для меня все еще намного безопаснее.
jpierson

51

Для полноты картины еще одно возможное решение (возможно, с меньшим набором текста):

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

(Конечно, Windowможно заменить на UserControl, и IntZeroможно определить ближе к месту фактического использования.)


44

Не знаю, почему WPFлюди не склонны к употреблению MarkupExtension. Это идеальное решение для многих проблем, включая проблему, упомянутую здесь.

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

Если это расширение разметки доступно в XAMLпространстве имен 'm', тогда исходный пример плаката станет:

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

Это работает, потому что синтаксический анализатор расширения разметки может видеть строгий тип аргумента конструктора и соответствующим образом преобразовывать, тогда как аргумент Binding ConverterParameter (менее информативно) типизирован для объекта.


Спасибо, это было полезно. Это будет мое первое расширение XAML. Но я думаю , что это лучше сделать вместо того , чтобы избежать бокс это каждый раз , когда в . (А затем сделайте так, чтобы напрямую не назначать что-то незаконное). ValueobjectintProvideValueprivate
Zeus

1
@Zeus Обычно ProvideValueвызывается только один раз для каждого экземпляра расширения разметки, поэтому упаковка в любом случае должна выполняться только один раз. Не делая этого в конструкторе, я вообще избегаю бокса, если ProvideValueон никогда не вызывается. Что касается Valueприватности, это не позволит использовать расширение разметки в XAMLсинтаксисе объектного элемента: msdn.microsoft.com/en-us/library/…
Гленн Слейден,

Ваш последний абзац неверен. Это называется преобразованием типа и также применяется к свойствам. Дело в том, что у Binding.ConverterParameterнего нет определенного типа (это просто object), поэтому синтаксический анализатор не знает, какое преобразование применить, поэтому каждый литерал обрабатывается просто как строка.
HB

(Так что, если бы у вашего расширения был конструктор по умолчанию, то он {m:Int32 Value=0}тоже работал бы.)
HB

5

Не используйте value.Equals. Использование:

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

8
Почему ты не хочешь использовать value.Equals?
Zack

1

Было бы неплохо как-то выразить информацию о типе ConverterValue в XAML, но я не думаю, что на данный момент это возможно. Итак, я предполагаю, что вам нужно проанализировать объект Converter для ожидаемого типа с помощью некоторой настраиваемой логики. Другого пути не вижу.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.