WPF: how to use 2 converters in 1 binding?
This is what I did:
public class CombiningConverter : IValueConverter{ public IValueConverter Converter1 { get; set; } public IValueConverter Converter2 { get; set; } public object Convert( object value, Type targetType, object parameter, CultureInfo culture) { object convertedValue = Converter1.Convert(value, targetType, parameter, culture); return Converter2.Convert( convertedValue, targetType, parameter, culture); } public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }}
and I call it like this:
<converters:CombiningConverter x:Key="negatedBoolToVisibilityConverter" Converter1="{StaticResource NegatedBooleanConverter}" Converter2="{StaticResource BoolToVisibilityConverter}" />
A MultiValueConverter
might also be possible I think. Maybe I'll try that later.
Expanding on Natrium's great answer...
XAML
<conv:ConverterChain x:Key="convBoolToInverseToVisibility"> <conv:BoolToInverseConverter /> <BooleanToVisibilityConverter /></conv:ConverterChain>
Class
/// <summary>Represents a chain of <see cref="IValueConverter"/>s to be executed in succession.</summary>[ContentProperty("Converters")][ContentWrapper(typeof(ValueConverterCollection))]public class ConverterChain : IValueConverter{ private readonly ValueConverterCollection _converters= new ValueConverterCollection(); /// <summary>Gets the converters to execute.</summary> public ValueConverterCollection Converters { get { return _converters; } } #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return Converters .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return Converters .Reverse() .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); } #endregion}/// <summary>Represents a collection of <see cref="IValueConverter"/>s.</summary>public sealed class ValueConverterCollection : Collection<IValueConverter> { }
In this case, you don't need a converter chain. You just need a configurable converter. This is similar to Carlo's answer above, but explicitly defines the true and false values (which means you can use the same converters for Hidden
, Visible
or Collapsed
conversions).
[ValueConversion(typeof(bool), typeof(Visibility))]public class BoolToVisibilityConverter : IValueConverter{ public Visibility TrueValue { get; set; } public Visibility FalseValue { get; set; } public BoolToVisibilityConverter() { // set defaults FalseValue = Visibility.Hidden; TrueValue = Visibility.Visible; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? TrueValue : FalseValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }}
Then in XAML:
<BoolToVisibilityConverter x:Key="BoolToVisibleConverter" FalseValue="Hidden" TrueValue="Visible" />