WPF BooleanToVisibilityConverter that converts to Hidden instead of Collapsed when false?

.NetWpfData BindingIvalueconverter

.Net Problem Overview


Is there a way to use the existing WPF BooleanToVisibilityConverter converter but have False values convert to Hidden instead of the default Collapsed, or should I just write my own? I'm on a project where it's tremendous overhead to do something simple like this (shared stuff goes into a separate solution, and the rebuild/checkin/merge process is an overgrown mutated behemoth of a process), so I'd prefer if I could just pass a parameter to the existing one than to jump through the hoops just mentioned.

.Net Solutions


Solution 1 - .Net

I've found the simplest and best solution to be this:

[ValueConversion(typeof(bool), typeof(Visibility))]
public sealed class BoolToVisibilityConverter : IValueConverter
{
  public Visibility TrueValue { get; set; }
  public Visibility FalseValue { get; set; }
  
  public BoolToVisibilityConverter()
  {
    // set defaults
    TrueValue = Visibility.Visible;
    FalseValue = Visibility.Collapsed;
  }
  
  public object Convert(object value, Type targetType, 
      object parameter, CultureInfo culture)
  {
    if (!(value is bool))
      return null;
    return (bool)value ? TrueValue : FalseValue;    
  }

  public object ConvertBack(object value, Type targetType, 
      object parameter, CultureInfo culture)
  {
    if (Equals(value, TrueValue))
      return true;
    if (Equals(value, FalseValue))
      return false;
    return null;
  }
}

When using it, just configure a version that does exactly what you need it to in XAML like this:

<Blah.Resources>
  <local:BoolToVisibilityConverter
         x:Key="BoolToHiddenConverter"
         TrueValue="Visible" FalseValue="Hidden" />
</Blah.Resources>

Then use it in one or more bindings like this:

<Foo Visibility="{Binding IsItFridayAlready, 
                          Converter={StaticResource BoolToHiddenConverter}}" />

This simple solution addresses hidden/collapsed preferences as well as reversing/negating the effect.

SILVERLIGHT USERS must drop the [ValueConversion] declaration as that attribute is not part of the Silverlight framework. It's not strictly needed in WPF either, but is consistent with built-in converters.

Solution 2 - .Net

Unfortunately, it only converts to Visible or Collapsed, so you'll have to write your own. Here is the Convert method according to Reflector:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    bool flag = false;
    if (value is bool)
    {
        flag = (bool)value;
    }
    else if (value is bool?)
    {
        bool? nullable = (bool?)value;
        flag = nullable.HasValue ? nullable.Value : false;
    }
    return (flag ? Visibility.Visible : Visibility.Collapsed);
}

Solution 3 - .Net

Can you not just use a style instead of a converter? The code would be something like:

<Style x:Key="Triggers" TargetType="Button">
    <Style.Triggers>
    <Trigger Property="{Binding ...}" Value="false">
        <Setter Property = "Visibility" Value="Hidden"/>
    </Trigger>
    </Style.Triggers>
</Style>

You'll need to provide the property binding yourself to point to your bool property.

Solution 4 - .Net

I like to use the parameter for reversing the visibility logic: To reverse logic simply put: ConverterParameter=Reverse in your xaml code

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    bool flag = false;
    if (value is bool)
    {
        flag = (bool)value;
    }

    var reverse = parameter as string;
    if(reverse != null && reverse == "Reverse")
        flag != flag;

    return (flag ? Visibility.Visible : Visibility.Collapsed);
}

Solution 5 - .Net

I wrote BoolToVisibilityConverte where you can pass invisible state in Parameter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var boolValue = (bool) value;
    return boolValue ? Visibility.Visible : (parameter ?? Visibility.Hidden);
}

So you can bind like this:

Visibility="{Binding SomeBool, Converter={StaticResource ResourceKey=BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Collapsed}}"

Hope this helps :)

Solution 6 - .Net

I had this issue crop up and my solution was probably very situational but I'll share it anyway. Due to my circumstance I was able to mimic the converter, without a converter, with a simple bit of code. I had visibility change only if a variable bound to a textbox made number box( through a Regex to ensure its a number) was not 0. The entire code for this is below however the WPF and first bit of C# is all you really need if you are going to change your boolean elsewhere in code. wpf:

    Visibility="{Binding Path=Visible}"

C#

    public class foo : INotifyPropertyChanged
    {
    	private bool vis = false;
    	public object Visible
    	{
    		get 
    		{ 
    			if (vis == true) 
    			{ 
    				return Visibility.Visible; 
    			} 
    			else 
    			{ 
    				return Visibility.Hidden; 
    			} 
    		}
    		set
    		{ 
    			vis = (bool)value; 
    			OnPropertyChanged(nameof(Visible)); 
    		}
    	}
    	public int Value_b
    	{
    		get 
    		{ 
    			return base_value;
    		}
    		set
    		{ 
    			base_value = value; 
    			OnPropertyChanged(nameof(Value_b));
    			if (base_value == 0) 
    			{ 
    				Visible = false; 
    			} 
    			else 
    			{ 
    				Visible = true; 
    			} 
    		}
    	}

    	public event PropertyChangedEventHandler PropertyChanged;
    	protected virtual void OnPropertyChanged(string propertyName)
    	{
    		PropertyChanged?.Invoke(this, new 
            PropertyChangedEventArgs(propertyName));
    	}
    }

Solution 7 - .Net

Using Caliburn.Micro, I have the following code that works for my simple use case and may work for others.

In my View, I have a button that I want to be hidden unless one of my variables has a positive length string:

<Button x:Name="SelectBinaryFilePath" Content="Select" Visibility="{Binding CanSelectBinaryFile}" />

In my ViewModel I have the following property:

public Visibility CanSelectBinaryFile
{
    get
    {
        return String.IsNullOrEmpty(FileSystemPath) ? Visibility.Hidden : Visibility.Visible;
    }
}

Ensure to do a NotifyOfPropertyChange to ensure the CanSelectBinaryFile prop is updated.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRichView Question on Stackoverflow
Solution 1 - .NetDrew NoakesView Answer on Stackoverflow
Solution 2 - .NetQuartermeisterView Answer on Stackoverflow
Solution 3 - .NetcristobalitoView Answer on Stackoverflow
Solution 4 - .NethkonView Answer on Stackoverflow
Solution 5 - .NetKrzysztof SkowronekView Answer on Stackoverflow
Solution 6 - .NetSteven AlbrightView Answer on Stackoverflow
Solution 7 - .NetMichael MurphyView Answer on Stackoverflow