Yet another extension to Town's answer. For my particular requirements I needed to pass parameters of a specific type, and a string-based solution like Trevi's answer did not support this.
My solution requires a bit of verbosity but as users of XAML we are no strangers to that ;)
public class ValueConverterChainParameters : List<object>
{
}
public class ValueConverterChain : List<IValueConverter>, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is not (null or ValueConverterChainParameters))
{
throw new ApplicationException($"{nameof(ValueConverterChain)} parameter must be empty/null or a {nameof(ValueConverterChainParameters)} instance where each element is the parameter to pass to the corresponding converter.");
}
ValueConverterChainParameters parameterList = parameter as ValueConverterChainParameters;
return this
.Select((converter, index) => (converter, index))
.Aggregate(value, (currentValue, element) =>
{
(IValueConverter converter, int index) = element;
return converter.Convert(currentValue, targetType, parameterList?[index], culture);
});
}
Usage below. In this scenario (somewhat contrived I know), the property MyAngle
on the templated parent is a string for some reason. The change type converter just does return System.Convert.ChangeType(value, targetType);
to get a double where one is expected on the Angle
property. This is then passed to my multiply converter which does a multiplication with the parameter.
<RotateTransform >
<RotateTransform.Angle>
<Binding Path="MyAngle" RelativeSource="{RelativeSource TemplatedParent}">
<Binding.Converter>
<conv:ValueConverterChain>
<conv:ChangeTypeConverter/>
<conv:MultiplyConverter/>
</conv:ValueConverterChain>
</Binding.Converter>
<Binding.ConverterParameter>
<conv:ValueConverterChainParameters>
<x:Null/>
<sys:Int32>-1</sys:Int32>
</conv:ValueConverterChainParameters>
</Binding.ConverterParameter>
</Binding>
</RotateTransform.Angle>
</RotateTransform>
Yes, it is a bit verbose, but it supports passing null
when you don't want to pass a parameter and passing parameters of specific types.