I was putting code in my ViewModel that returns Visibility but I didn’t really like that very much. If the UI is created with something other than WPF, that is really not going to work. Since I intend to do cross compile my code in Mono, which doesn’t have WPF but uses either Forms or GTK#, I have already encountered this issue. What I really want to use is bool.

The solution is IValueConverter. If you just want the code and don’t want to read this post, just scroll to the bottom and grab the

IValueConverter is part of PresentationFramework (in PresentationFramework.dll) so it isn’t available in Mono, but that is OK because you don’t instantiate it in the ViewModel, you use it in the View so it will only be used when the GUI is part of WPF. So if you are separating your View into a separate DLL, this would be included in the View DLL, that way when you compile everything else, with say a different GUI that uses GTK#, you won’t get a compiler error because PresentationFramework doesn’t exist in Mono.

BooleanToVisibilityConverter

Well, there is an object already created for you called BooleanToVisibilityConverter, but it is limited. True is converted Visibility.Visible. False is converted to Visibility.Collapsed.

Here we see a problem. Visibility has three possible values but a Boolean only has two.

Here is a simple View for this object. It has a Grid that has a Label and TextBox for each property in the Person object. It also has a CheckBox. The CheckBox gives us a easy bool value, IsChecked. This works similar to a bool property in a ViewModel.

Ok, now build the project and you will see that the Label and TextBox for Age are hidden until you check the box.

Writing your own Bool to Visibility Converter

Sometimes you may need to write you own Converter. For example, in the above project, it is annoying how the CheckBox moves up and down in position because Visibility.Collapsed is used instead of Visibility.Hidden. You may want to use Visibility.Hidden instead.

You can write your own Converter that returns Visibility.Hidden instead of Visibility.Collapsed.

Here we do the conversion ourselves and now we have a different conversion table.

Boolean

Visibility

True

Visible

Collapsed

False

Hidden

Now replace the Converter object in your XAML. We only change Line 15.

<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter"/>

This works, but it could be improved. This still leaves us having to choose between two objects.

Creating a Converter that supports a choice of Hidden or Collapsed.

Here we will provide a property that determines if we should collapse or not.

Add a property called Collapse and return the appropriate Visibility based on that property. Here is the new object. As you see, the code changes to add this feature is really just an empty bool property and an if statement that used the bool property.

We now support either feature with the following table. We probably at this point would rename the object to BooleanToVisibilityConverter, but Microsoft already took that object name so I will leave it named as is.

Boolean

Visibility

True

Visible

False – Collapse=True

Collapsed

False – Collapse=False

Hidden

We are starting to get a little more usability from one object.

Adding the Reverse feature so False is Visible and True is Collapsed or Hidden

Lets say we want to change the CheckBox so that instead of saying “Show Age” it says “Hide Age”.

<CheckBox Name="ShowAgeCheckBox" Content="Hide Age" />

Now we have to reverse the mapping. If Reverse=”True” we want the mapping to be like this:

Boolean

Visibility

False

Visible

True – Collapse=True

Collapsed

True – Collapse=False

Hidden

This is also quite simple. We add another bool property called Reverse. Then key of that in another if statement.

Additional Thoughts

I have to wonder why the developers didn’t do this originally with the BooleanToVisibilityConverter object. It is so simple. This is a perfect example of where Microsoft would benefit from Open Sourcing some of their code. A dozen people would have contributed this change by now if they had and all Microsoft would have to do is look at the submitted code, approve, and check it in.

You don't necessarily have to define it in Grid.Resources. It just needs to exist somewhere in any parent's resources. This is because WPF currently requires that an instance of BooleanToVisibilityConverter exists prior to us.

My other blogs

Entries (RSS) and Comments (RSS). Copyright ® Rhyous.com Linking to content on this site is allowed without permission and as many as ten lines of any article can be used along with such link. Any other use of the content is allowed only by permission of Rhyous.com.