how to pass an integer as ConverterParameter?

2019-01-30 21:19发布

问题:

I am trying to bind to an integer property:

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

and my converter is:

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

the problem is that when my converter is called the parameter is string. i need it to be an integer. of course i can parse the string, but do i have to?

thanks for any help konstantin

回答1:

Here ya go!

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

The trick is to include the namespace for the basic system types and then to write at least the ConverterParameter binding in element form.



回答2:

For completeness, one more possible solution (perhaps with less typing):

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

(Of course, Window can be replaced with UserControl, and IntZero may be defined closer to the place of actual usage.)



回答3:

Not sure why WPF folks tend to be disinclined towards using MarkupExtension. It is the perfect solution for many problems including the issue mentioned here.

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

If this markup extension is available in XAML namespace 'm', then the original poster's example becomes:

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

This works because the markup extension parser can see the strong type of the constructor argument and convert accordingly, whereas Binding's ConverterParameter argument is (less-informatively) Object-typed.



回答4:

Don't use value.Equals. Use:

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


回答5:

It would be nice to somehow express the type information for the ConverterValue in XAML, but I don't think it is possible as of now. So I guess you have to parse the Converter Object to your expected type by some custom logic. I don't see another way.