Is there a way to chain multiple value converters in XAML?
I used this method by Gareth Evans in my Silverlight project.
Here's my implementation of it:
public class ValueConverterGroup : List<IValueConverter>, IValueConverter{ #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } #endregion}
Which can then be used in XAML like this:
<c:ValueConverterGroup x:Key="InvertAndVisibilitate"> <c:BooleanInverterConverter/> <c:BooleanToVisibilityConverter/></c:ValueConverterGroup>
Found exactly what I was looking for, courtesy of Josh Smith: Piping Value Converters (archive.org link).
He defines a ValueConverterGroup
class, whose use in XAML is exactly as I was hoping for. Here's an example:
<!-- Converts the Status attribute text to a SolidColorBrush used to draw the output of statusDisplayNameGroup. --><local:ValueConverterGroup x:Key="statusForegroundGroup"> <local:IntegerStringToProcessingStateConverter /> <local:ProcessingStateToColorConverter /> <local:ColorToSolidColorBrushConverter /></local:ValueConverterGroup>
Great stuff. Thanks, Josh. :)
Town's implementation of Gareth Evans's Silverlight project is great, however it does not support different converter parameters.
I modified it so you can provide parameters, comma delimited (unless you escape them of course).
Converter:
public class ValueConverterGroup : List<IValueConverter>, IValueConverter{ private string[] _parameters; public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if(parameter != null) _parameters = Regex.Split(parameter.ToString(), @"(?<!\\),"); return (this).Aggregate(value, (current, converter) => converter.Convert(current, targetType, GetParameter(converter), culture)); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } private string GetParameter(IValueConverter converter) { if (_parameters == null) return null; var index = IndexOf(converter as IValueConverter); string parameter; try { parameter = _parameters[index]; } catch (IndexOutOfRangeException ex) { parameter = null; } if (parameter != null) parameter = Regex.Unescape(parameter); return parameter; }}
Note: ConvertBack is not implemented here, see my Gist for the full version.
Implementation:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:ATXF.Converters;assembly=ATXF" x:Class="ATXF.TestPage"> <ResourceDictionary> <converters:ValueConverterGroup x:Key="converters"> <converters:ConverterOne /> <converters:ConverterTwo /> </converters:ValueConverterGroup> </ResourceDictionary> <Label Text="{Binding InitialValue, Converter={StaticResource converters}, ConverterParameter='Parameter1,Parameter2'}" /></ContentPage>