як передати ціле число як 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 буде передано у вигляді рядка
Кшиштоф Качор

Відповіді:


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. Вам все одно доведеться кинути / проаналізувати це ...
Dan J

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

Це працює, оскільки аналізатор розширення розмітки може бачити сильний тип аргументу конструктора і відповідно перетворювати, тоді як аргумент ConverterParameter Binding (менш інформативно) вводиться як об'єкт.


Дякую, це було корисно. Це буде моє перше розширення XAML. Але я думаю , що це краще зробити замість того , щоб уникнути бокс це кожен раз , коли в . (А потім, зробіть це, щоб уникнути прямого призначення чогось незаконного). ValueobjectintProvideValueprivate
Зевс

1
@Zeus Зазвичай ProvideValueвикликається лише один раз на екземпляр розширення розмітки, тому бокс у будь-якому випадку повинен відбуватися лише один раз. Не роблячи цього в конструкторі, я взагалі уникаю боксу, якщо ProvideValueйого ніколи не викликають. Що стосується Valueприватності, це виключає використання розширення розмітки в XAMLсинтаксисі елемента об’єкта: msdn.microsoft.com/en-us/library/…
Гленн Слейден,

Ваш останній абзац помилковий. Це називається перетворенням типу, і воно також стосується властивостей. Справа в тому, що у Binding.ConverterParameterнього немає конкретного типу (це просто an object), тому синтаксичний аналізатор не знає, яку конверсію застосувати, отже, кожен літерал просто трактується як рядок.
HB

(Отже, якби у вашому розширенні був конструктор за замовчуванням, він {m:Int32 Value=0}би працював так само добре.)
HB

5

Не використовуйте value.Equals. Використання:

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

8
Чому ви не хочете використовувати value.Equals?
Зак

1

Було б непогано якось висловити інформацію про тип для ConverterValue в XAML, але я не думаю, що це можливо зараз. Отже, я думаю, вам доведеться проаналізувати об’єкт конвертера за очікуваним типом за певною логікою. Я не бачу іншого шляху.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.