指定IValueConverter的目标类型
本文关键字:类型 目标 IValueConverter 指定 | 更新日期: 2023-09-27 18:01:23
我有一个情况,我正在使用一个多值转换器。传递给它的值本身正在被转换。
<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的目标类型传递呢?
按要求这里是布尔anandconverter代码:
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 ?当不用于多绑定情况时,它总是根据要转换的内容正确指定。
使用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上,你可以找到一些关于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();
}
}
如果object
是目标类型,则值转换器实现应该执行适当的默认转换。如果绑定转换器返回错误的类型,您将获得绑定调试错误输出,您可以相应地修复问题。您也不应该在转换器中抛出错误,您应该通过Debug.WriteLine
输出信息并返回DependencyProperty.UnsetValue
。
由于这种情况,通常不建议根据targetType
参数返回多种类型的结果,并且应该很明显转换器将返回哪种类型的值。您可以忽略targetType
,或者检查它是否是正确的类型或object
。实际上,这并没有什么区别。
在我看来,转换器中的代码应该将对象强制转换为它期望的任何类型。
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将其作为特定类型传递。如果您希望转换器对不同类型的行为不同,您可以将类型作为转换器参数包含,或者您可以使用多值转换器以不同的方式转换每个参数