views:

68

answers:

4

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.

+4  A: 

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);
}
Quartermeister
A: 

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.

cristobalito
It's quite wasteful to use styles and triggers every time for such a common conversion - that's why we have these common converters!
Dan Puzey
I agree. This totally works, but I hate how much code it adds to my xaml. This project has tons of this kind of stuff going on and I find it makes reading it really difficult the more you have. I'd love to know if there's a performance difference to the two approaches.
Rich
I don't honestly know - I'm a newbie to the whole WPF stuff. Until Dan mentioned there might be a performance issue, I certainly never had considered it, but it's an interesting question.Does this really add that much code to your XAML though - it's a keyed style, so you can just reference it where needed. Alternatively, you can also base styles of other styles, thereby adding possible re-use points. See http://msdn.microsoft.com/en-us/library/system.windows.style.basedon.aspx
cristobalito
It's only an issue when you've got a really big project like the one I'm working on. What it really comes down to is on a per-case basis. In my case, making anything new that is reusable means rebuilding an external project and deploying the dll's, and when you have at least 50 devs on the same project checking in all day long, you look to avoid this at all cost. Plus, our xaml files keep growing and growing, so I'm really looking to keep everything as minimal as possible unless there's a significant performance gain with the more verbose solution.
Rich
A: 

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);
}
hkon
+2  A: 

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.

Drew Noakes
Note that I typed this out in a text editor. If anyone finds an error, please let me know and I'll update the code.
Drew Noakes