Category Archives: Binding

One VisibilityConverter to Rule Them All

One long-running irritation I’ve had with the Silverlight XAML rendering engine is that it refuses to make a best guess for values when bound to an element’s Visibility property. One would think that binding a boolean value to Visibility would make sense in particular, but unless the value is a System.Windows.Visibility enumeration value your binding will silently fail to update the binding target. To resolve this frustration, I created a custom VisibilityConverter IValueConverter implementation that maps most common data types in a sane way.

In short, this implementation compares the type of the supplied “value” parameter against a series of known types. When a match is found, it applies individualized logic to determine whether to return Visibility.Visible or Visibility.Collapsed.

public class VisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        bool isVisible = false;

        if (value is bool || value is bool?)
            isVisible = (bool?)value == true;
        else if (value is double) isVisible = (double)value != 0;
        else if (value is long) isVisible = (long)value != 0;
        else if (value is int) isVisible = (int)value != 0;
        else if (value is float) isVisible = (float)value != 0;
        else if (value is short) isVisible = (short)value != 0;
        else if (value is byte) isVisible = (byte)value != 0;
        else isVisible = value != null;

        if (ObjectToBool(parameter))
            isVisible = !isVisible;

        return isVisible ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        throw new InvalidOperationException();
    }
}

You’ll note at the end the call to ObjectToBool(…). This allows you to invert the behavior of the VisibilityConverter, which is particularly useful for addressing error conditions,¬†using the converter parameter such that falses, 0’s, and nulls become visible. Since the parameter type can vary depending on whether it’s supplied from a static resource or entered as a string in the binding expression by hand, a special function is required for resolving it.

public static bool ObjectToBool(object boolObject, bool nullValue = false)
{
    bool toggle = false;

    if (boolObject != null)
    {
        if (boolObject is bool)
            toggle = (bool)boolObject;
        else if (boolObject is bool?)
            toggle = (bool?)boolObject == true;
        else if (boolObject is string)
        {
            if (!Boolean.TryParse((string)boolObject, out toggle))
                toggle = false;
        }
    }
    else
        toggle = nullValue;

    return toggle;
}

A trick that I’ve found to be very helpful is to define some of these general purpose converters in your App.xaml file, which allows them to be accessed from any controls you have in your project using a static resource reference. Here’s an example of what that might look like.

<TextBlock Text="No results found."
           Visibility="{Binding Path=Results.Count,
                        Converter={StaticResource VisibilityConverter},
                        ConverterParameter=True}" />

Hope this helps, and please post if you have any ideas on how to simplify this any further!