【问题标题】:Specify target type for IValueConverter为 IValueConverter 指定目标类型
【发布时间】:2015-07-07 19:06:22
【问题描述】:

我有一种使用多值转换器的情况。传递给它的值本身正在被转换。

<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?在多绑定情况下不使用时,总是会根据正在转换的内容正确指定。

【问题讨论】:

  • 它只是一个装箱的布尔值吗?你是否在调试器中查看过它以确定传入的对象的底层类型?
  • 请发布 BooleanAndConverter 的代码。
  • @AbinMathew 我在问题中添加了转换函数。
  • "如何正确指定 targetType?"当 Converter1 用于 MultiBinding 中的 Binding 时,一点也​​不。没有目标属性,因此除了object 之外没有目标类型。
  • 在 4.0 中由于某种原因从 .NET 3.5 发生了变化,请参阅 stackoverflow.com/questions/19086116/…

标签: c# wpf xaml ivalueconverter imultivalueconverter


【解决方案1】:

使用 CommandParameter 的某些 cmets 的可能替代方案可能是 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 上,您可以找到几篇关于 Markupextension-Converters 的帖子,例如 here

两种方式的示例实现:

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

【讨论】:

  • 我喜欢这个解决方案,因为它仍然允许类型检查来帮助避免运行时错误。如果提供了参数,您可以使其检查参数,否则它将检查目标类型。我最终采取了稍微不同的方法。相反,我选择检查我想要返回的类型是否可以安全地转换为目标类型。 if (!targetType.IsAssignableFrom(typeof(TheTypeIWantToReturn))) {}
【解决方案2】:

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

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 将其作为特定类型传入。如果您希望转换器对不同类型的行为有所不同,您可以将类型作为转换器参数包含在内,或者您可以使用多值转换器对每个参数进行不同的转换

【讨论】:

  • 不是值的类型有问题。 value 是显式传入的。它是未指定的 targetType。
【解决方案3】:

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

由于这种情况,通常不建议根据targetType 参数返回超过一种类型的结果,并且转换器将返回什么类型的值应该很明显。您可以忽略targetType,或者检查它是否是正确的类型或object。实际上,它并没有真正的区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 2020-09-01
    • 2011-09-22
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多