WPF: how to use 2 converters in 1 binding?

Viewed 35350

I have a control that I want to show/hide, depending on the value of a boolean.

I have a NegatedBooleanConverter (switches true to false and vice versa) and I need to run this converter first. I have a BooleanToVisibilityConverter and I need to run this converter after the NegatedBoolConverter.

How can I fix this problem? I want to do this in XAML.

edit: this is a possible solution.

That doesn't seem to work. It first converts the value with the separate converters and then does something with the converted values.

What I need is:

  • Convert the value with the first converter (this gives convertedValue).
  • Convert convertedValue with the second converter and it's this result that I need.
11 Answers

At this point I'd like to suggest ValueConverters.NET (NuGet) which has a ton of useful ValueConverters, including the ValueConverterGroup that can be used to combine ValueConverters.

BoolToValueConverters also offer fields to define the TrueValue, FalseValue as well as if the input IsInverted, so a ValueConverterGroup is not even necessary in most cases.

Just to illustrate how easy the life can get, here is a sample demonstration which shows a converter that displays an element if the binding is not null:

<Window ...
        xmlns:vc="clr-namespace:ValueConverters;assembly=ValueConverters"
        ...>
...
    <vc:ValueConverterGroup x:Key="IsNotNullToVisibilityConverter">
      <vc:NullToBoolConverter IsInverted="True" />
      <vc:BoolToVisibilityConverter />
    </vc:ValueConverterGroup>

ValueConverters are a prime example of reinventions of the wheel in a lot of WPF applications. Why it has to be?

Also complex things can often be solved with StyleTriggers or within the ViewModels logic itself.

It almost never happens that I need to build a custom converter. In my opinion WPF has enough engineer requirements already.

Here is a combination of Natrium and metao answers to save you some time:

public class ComparisonConverter : IValueConverter
{
    public object TrueValue { get; set; } = true;
    public object FalseValue { get; set; } = false;


    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(parameter) == true? TrueValue : FalseValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(TrueValue) == true ? parameter : Binding.DoNothing;
    }
}

And how you use it:

<converter:ComparisonConverter x:Key="ComparisonConverter" />
<converter:ComparisonConverter TrueValue="{x:Static Visibility.Visible}"
                               FalseValue="{x:Static Visibility.Collapsed}"
                               x:Key="ComparisonToVisibilityConverter" />
...

<RadioButton IsChecked="{Binding Type, ConverterParameter={x:Static entities:LimitType.MinMax}, Converter={StaticResource ComparisonConverter}}"/>
<TextBox Visibility="{Binding Type, ConverterParameter={x:Static entities:LimitType.MinMax}, Converter={StaticResource ComparisonToVisibilityConverter}}"/>
Related