如何传递一个整数作为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平台上实现这一点吗?在Windows Phone平台上,绑定的语法略有不同?此示例中的{Binding属性,Converter = {StaticResource MYCONVERTER},ConverterParameter = INT_VAL} INT_VAL将作为字符串传递
Krzysztof

Answers:


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()' parameter'参数类型为的事实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}}" />

之所以可行,是因为标记扩展解析器可以看到构造函数参数的强类型并进行相应的转换,而Binding的ConverterParameter参数是(信息较少)对象类型的。


谢谢,这很有用。这将是我的第一个XAML扩展。但是我认为最好制作Value一个,object而不是int每次都不要装箱ProvideValue。(然后,private避免直接分配非法的东西)。
宙斯

1
@Zeus通常ProvideValue每个标记扩展实例仅调用一次,因此装箱无论如何应该只发生一次。通过不在构造函数中执行此操作,可以避免完全装箱(如果ProvideValue从未调用过)。至于做Value私人的,这将排除使用标记扩展XAML:对象元素语法msdn.microsoft.com/en-us/library/...
格伦Slayden

您的最后一段是错误的。这称为类型转换,它也适用于属性。事实是,它Binding.ConverterParameter没有特定的类型(只是一个object),因此解析器不知道要应用哪种转换,因此每个文字都被视为一个字符串。
HB

(因此,如果您的扩展名具有默认构造函数,则其效果{m:Int32 Value=0}也一样。)
HB


1

最好以某种方式在XAML中表示ConverterValue的类型信息,但我认为目前还不可能。因此,我想您必须通过一些自定义逻辑将Converter Object解析为所需的类型。我没有其他办法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.