如何将整数作为ConverterParameter传递?

105
我想要绑定一个整数属性:
<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;
    }
}

问题在于当我的转换器被调用时,参数是字符串。我需要它是一个整数。当然,我可以解析这个字符串,但是我必须这样做吗?

谢谢任何帮助 Konstantin


2
有人知道如何在Windows Phone平台上实现这个功能吗?因为我们在绑定语法方面与其他平台略有不同。在此示例中,INT_VAL将作为字符串传递。{Binding PROPERTY,Converter = {StaticResource MYCONVERTER},ConverterParameter = INT_VAL} - Krzysztof Kaczor
5个回答

129

给你了!

<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

63

为了完整性,还有一种可能的解决方案(也许输入更少):

<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可以在实际使用的地方更靠近定义。


58

我不确定为什么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命名空间'local:'中定义,那么原帖作者的示例就变成了:
<RadioButton Content="None"
             IsChecked="{Binding MyProperty,
                         Converter={StaticResource IntToBoolConverter},
                         ConverterParameter={local:Int32 0}}" />

这起作用是因为标记扩展解析程序可以看到构造函数参数的强类型并进行相应转换,而Binding的ConverterParameter参数是(信息较少的)Object类型。


谢谢,这很有用。这将是我的第一个XAML扩展。但我认为最好将“Value”作为“object”而不是“int”,以避免在“ProvideValue”中每次装箱。(然后,将其设置为“private”以避免直接分配非法内容)。 - Zeus
1
@Zeus 通常情况下,每个标记扩展实例只调用一次ProvideValue,因此装箱应该只会发生一次。如果不在构造函数中执行装箱操作,如果从未调用ProvideValue,则可以完全避免装箱问题。至于使“Value”成为私有的,这将排除在“XAML”对象元素语法中使用标记扩展的可能性:https://msdn.microsoft.com/zh-cn/library/ms788723(v=vs.100).aspx#object_element_syntax - Glenn Slayden
你最后一段说错了。它被称为类型转换,也适用于属性。问题在于,Binding.ConverterParameter 没有特定的类型(它只是一个 object),所以解析器不知道要应用什么转换,因此每个字面量都被视为字符串。 - H.B.
(所以,如果您的扩展具有默认构造函数,则“{m:Int32 Value = 0}”也可以正常工作。) - H.B.

4
不要使用value.Equals,应该使用:
  Convert.ToInt32(value) == Convert.ToInt32(parameter)

9
为什么您不想使用 value.Equals - Zack
由于值可能为空(如果它是可空类型),会导致ArgumentNullException错误。 - Anup Sharma

0

在 XAML 中以某种方式表达 ConverterValue 的类型信息会很好,但我认为目前不可能实现。因此,我猜您需要通过一些自定义逻辑来解析转换器对象以符合您期望的类型。我没有看到其他方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接