views:

592

answers:

3

Hi All

I want to bind a controls visibility to inverse of boolean property value. I have a property CanDownload, if it is true then I want to hide textbox and vice versa. How can I achieve this?

Thanks

A: 

I was able to solve this for a recent project using a bool to visibility converter:

public class BoolToVisibilityConverter : IValueConverter
{

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value.GetType().Equals(typeof(bool)))
        {
            if ((bool)value == true)
                return Visibility.Visible;
            else
                return Visibility.Collapsed;
        }
        else
            return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value.GetType().Equals(typeof(Visibility)))
        {
            if ((Visibility)value == Visibility.Collapsed)
                return false;
            else
                return true;
        }
        else
            return false;

    }

    #endregion
}    

I think I could have probably replaced this line:

if (value.GetType().Equals(typeof(Visibility)))

with something more simple like this:

if (value is Visibility)

same with the bool GetType, but you get the idea.

Of course, in your converter you can reverse the visility values based on your visibility needs. Hope this helps a little.

TruncatedCoDr
+1  A: 

I use a BoolToVisibilityConverter that allows you to pass "Inverse" as the ConverterParameter to inverse the conversion and show only if the property is false.

public class BoolToVisibilityConverter : IValueConverter
{
    /// <exception cref="ArgumentException">TargetType must be Visibility</exception>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if(!(value is bool))
            throw new ArgumentException("Source must be of type bool");

        if(targetType != typeof(Visibility))
            throw new ArgumentException("TargetType must be Visibility");

        bool v = (bool) value;

        if(parameter is string && parameter.ToString() == "Inverse")
            v = !v;

        if (v)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Stephan
This is ideal since you only need one parameter.
infamouse
+2  A: 

This sort of question is asked so often and the answers so similar I thought its time to have a single answer to all (ok may "most") of the bool to value conversion questions. I've blogged it here.

The code is quite simple so I'll paste it here too:-

public class BoolToValueConverter<T> : IValueConverter
{
    public T FalseValue { get; set; }
    public T TrueValue { get; set; }

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

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

Now you can create converter to visibility with a one-liner:-

public class BoolToVisibilityConverter : BoolToValueConverter<Visibility> { }

Then for you can create an instance converter in a resource like this:-

<local:BoolToVisibilityConverter x:Key="InverseVisibility" TrueValue="Collapsed" FalseValue="Visible" />

Note the TrueValue and FalseValue are the swapped around from the more natural order giving you the inverted logic you wanted. With this in the Resources in your UserControl or even App.xaml you can now use it to bind to the CanDownload property to TextBox Visibility property:-

<TextBox Visibility="{Binding CanDownload, Converter={StaticResource InverseVisibility}}" />
AnthonyWJones
great. thanks for reply. that is what i was looking for.
joblot
i am having a strange issue. when i step into the Convert method and hover over targetType it says System.Windows.Visibility but check if(targetType is Visibility) fails. when i do targetType.GetType().ToString() in immediate window it returns System.RuntimeType! i am confused what is happening here
joblot
this is how i am binding <Button Content="Save" Width="100" MaxWidth="100" x:Name="saveButton" Visibility="{Binding CanDownloadVols, Converter={StaticResource visibilityConverter}}"/>
joblot
@joblot: The `targetType` parameter is of __type__ `System.Type`, in this case it currently has the __value__ of `System.Windows.Visibility`. (Read that again carefully this is one those "algebra" moments where nothing else can makes sense until the penny drops.) When you do `targetType.GetType()` now you've got a `Type` which has the value of a `Type`, in this case `System.RuntimeType` which derives from `System.Type`. If that last sentence doesn't make sense it because you haven't yet grasped my first sentence. See:- http://msdn.microsoft.com/en-us/library/system.type(v=VS.100).aspx
AnthonyWJones
You could improve the class slightly by utilizing the parameter argument to invert (or not) the returned value.
Lillemanden