我试图将转换器作为Town的回答链接到Is there a way to chain multiple value converters in XAML??
我还希望通过targetType检查来使单个转换器更严格: -
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a
boolean");
但是链条失败,因为最终目标类型与每个阶段的目标不同。
我可以删除类型检查以使其不那么严格,如SO中的大多数示例所示,但我更喜欢链接,它也考虑每个转换器的类型检查。例如。为了更好的单元测试等。
界面IValueConverter也没有暴露目标类型,我发现很难自己添加检查。
public class InverseBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
if (!(value is bool))
throw new ArgumentException("Argument 'value' must be of type bool");
return !(bool)value;
}
....
}
[ValueConversion(typeof(bool), typeof(Visibility))]
public class VisibilityFromBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(Visibility))
throw new InvalidOperationException("The target must be a Visibility");
if (!(value is bool))
throw new ArgumentException("Argument 'value' must be of type bool");
var isVisible = (bool)value;
return isVisible ? Visibility.Visible : Visibility.Collapsed;
}
....
}
复合材料就像: -
<Converters:ValueConverterGroup x:Key="InvertAndVisible">
<Converters:InverseBooleanConverter />
<Converters:VisibilityFromBoolConverter />
</Converters:ValueConverterGroup>
但我从InverseBooleanConverter获得异常“目标必须是布尔值”,因为它期望目标是bool而不是Visibility(链的最终目标)。
答案 0 :(得分:0)
原始的ValueConverterGroup代码将最终的targetType传递到每个阶段,这就是您的检查失败的原因。您需要做的就是修改该行为以传递下一个转换器targetType:
[ValueConversion(typeof(bool), typeof(Visibility))]
public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
for (int i = 0; i < this.Count(); i++)
{
var targ = (i == this.Count() - 1)
? targetType
: (this[i + 1].GetType().GetCustomAttributes(typeof(ValueConversionAttribute), false).First() as ValueConversionAttribute).SourceType;
value = this[i].Convert(value, targ, parameter, culture);
}
if (value.GetType() != (this.GetType().GetCustomAttributes(typeof(ValueConversionAttribute), false).First() as ValueConversionAttribute).TargetType)
throw new InvalidOperationException("Last target must be of type " + targetType.Name);
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}