wpf 为 IValueConverter 指定目标类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31277261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:15:17  来源:igfitidea点击:

Specify target type for IValueConverter

c#wpfxamlivalueconverterimultivalueconverter

提问by denver

I have a situation where I am using a multi-value converter. The values passed to it are themselves being converted.

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

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

Converter1 contains some error checking to confirm that it is called with a valid target type. It throws an exception if not, as this is a developer error and the situation should be fixed.

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

The problem is that when Converter1 is used in this context the target type is System.Object. Now the BooleanAndConverter requires values of a certain type (Boolean), so how can I get that type passed as the target type of Converter1?

问题在于,在此上下文中使用 Converter1 时,目标类型是 System.Object。现在 BooleanAndConverter 需要某种类型(Boolean)的值,那么我怎样才能将该类型作为 Converter1 的目标类型传递呢?

As requested here is the BooleanAndConverter code:

这里要求的是 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;
    }

Let me restate the question as there seems to be some confusion. Converter1 knows what type it can convert from and to. It throws an exception when called with the wrong types. In this situation the targetType is not getting specified and an exception is being thrown. How do I get the targetType specified correctly? When not used in a multi-binding situation is does always get specified correctly based on what is being converted.

让我重申一下这个问题,因为似乎有些混乱。Converter1 知道它可以从什么类型转换到什么类型。使用错误的类型调用时会引发异常。在这种情况下,未指定 targetType 并引发异常。如何正确指定 targetType?当不用于多绑定情况时,总是会根据正在转换的内容正确指定。

采纳答案by Frederick

An possible alternative to some comments using a CommandParameter could be a MarkupExtension. Then you could write your MultiBinding like:

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

On StackOverflow you can find several posts about Markupextension-Converters like here.

在 StackOverflow 上,你可以找到几篇关于 Markupextension-Converters 的帖子,比如这里

Sample implementation for both ways:

两种方式的示例实现:

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

回答by MatrixManAtYrService

Seems to me that the code in the converter should be casting the object to whatever type it expects.

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

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
 }

I do not know of a way get WPF to pass it in as a specific type. If you want the converter to behave differently for different types you could include the type as a converter parameter, or you could use a multivalueconverter to cast each parameter differently

我不知道有什么方法可以让 WPF 将它作为特定类型传入。如果您希望转换器对不同类型的行为不同,您可以将该类型作为转换器参数包含在内,或者您可以使用多值转换器以不同方式转换每个参数

回答by Mike Marynowski

Value converter implementations should do an appropriate default conversion if objectis the target type. You will get binding debug errors output if a bound converter is returning the wrong type and you can fix the problem accordingly. You also shouldn't be throwing errors in converters, you should output an informative message via Debug.WriteLineand return DependencyProperty.UnsetValue.

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

Because of situations like this it is generally not recommended to return more than one type of result based on the targetTypeparameter and it should be obvious what type of value the converter will return. You can either ignore targetType, or check that it is either the correct type or object. In practice it doesn't really make a difference.

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