指定IValueConverter的目标类型

时间:2015-07-07 19:06:22

标签: c# wpf xaml ivalueconverter imultivalueconverter

我遇到的情况是我使用的是多值转换器。传递给它的值本身正在转换。

<MenuItem>
    <MenuItem.IsEnabled>
        <MultiBinding Converter="{StaticResource BooleanAndConverter}">
            <Binding Path="Prop1" Converter="{StaticResource Converter1}" />
            <Binding Path="Prop2" Converter="{StaticResource Converter1}" />
        </MultiBinding>
    </MenuItem.IsEnabled>
</MenuItem

Converter1包含一些错误检查,以确认使用有效的目标类型调用它。如果没有,它会引发异常,因为这是开发人员错误,应该修复情况。

问题是当在此上下文中使用Converter1时,目标类型是System.Object。现在BooleanAndConverter需要某种类型的值(布尔值),那么如何将该类型作为Converter1的目标类型传递?

这里要求的是BooleanAndConverter代码:

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        foreach (object value in values)
        {
            if (value.GetType() != typeof(bool))
            {
                throw new ArgumentException("BooleanAndConverter can only be used to convert booleans."); // developer error
            }
        }

        if (targetType != typeof(bool))
        {
            throw new ArgumentException("BooleanAndConverter can only convert to a boolean."); // developer error
        }

        foreach (object value in values)
        {
            if ((bool)value == false)
            {
                return false;
            }
        }
        return true;
    }

让我重申这个问题,因为似乎有些混乱。 Converter1知道它可以转换的类型。使用错误的类型调用时会抛出异常。在这种情况下,未指定targetType并抛出异常。如何正确指定targetType?如果未在多绑定情况下使用,则始终根据要转换的内容正确指定。

3 个答案:

答案 0 :(得分:0)

在我看来,转换器中的代码应该将对象转换为它所期望的任何类型。

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var desired = value as desiredType;
    if (desired != null)
        //do stuff with 'desired' as a parameter
    else
        // error
 }

我不知道如何让WPF将其作为特定类型传递。如果您希望转换器对于不同类型的行为不同,您可以将类型包括为转换器参数,或者您可以使用多值转换器以不同方式转换每个参数

答案 1 :(得分:0)

使用CommandParameter的一些注释的可能替代方法可能是MarkupExtension。然后你可以编写你的MultiBinding,如:

<MultiBinding Converter="{StaticResource BooleanAndConverter}">
  <Binding Path="Prop1" Converter="{conv:DebugTypeCheck, CheckType={x:Type sys:Boolean}" />
  <Binding Path="Prop2" Converter="{StaticResource DebugTypeCheckConverter}" CommandParameters="{x:Type sys:Boolean}" />
</MultiBinding>

在StackOverflow上,您可以找到有关像here这样的Markupextension-Converters的几篇帖子。

两种方式的示例实现:

public class DebugTypeCheck : MarkupExtension, IValueConverter
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public Type CheckType { get; set; }

    [Conditional("DEBUG")]
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value.GetType() != CheckType)
        {
            throw new ArgumentException(); // developer error
        }

        return value;
    }  

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    } 
}

public class DebugTypeCheckConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value.GetType() != (Type)parameter)
        {
            throw new ArgumentException(); // developer error
        }

        return value;
    }  

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    } 
}

答案 2 :(得分:0)

如果object是目标类型,则值转换器实现应进行适当的默认转换。如果绑定的转换器返回错误的类型,您将获得绑定的调试错误输出,并且可以相应地解决此问题。您也不应在转换器中引发错误,应该通过Debug.WriteLine输出信息性消息并返回DependencyProperty.UnsetValue

由于这种情况,通常不建议基于targetType参数返回一种以上类型的结果,并且很明显转换器将返回哪种类型的值。您可以忽略targetType,也可以检查它是正确的类型还是object。实际上,它并没有真正的改变。