Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Bool To Content Converter

0.00/5 (No votes)
15 Nov 2013 1  
Bool to content converter

Introduction

I've created a lot of bindings to boolean values that required a converter of some kind. And, I've found that a simple bool to object converter takes care of a lot of my problems. At first, I would create a user control or converter for just about everything; I've seen a few other people go down that same path.

Need to set the background image on a button based on some bool value of the selected item, write a bool to BitmapImage converter. Need to set a text color, based on the success of an operation, write a bool to Brush converter. That bool to Brush converter was originally a bool to SolidColorBrush converter, but as soon as I wrote that, I thought, that's way too specific. Switching that converter from solid color brush to just brush made me realize that I could have just done a BoolToObjectConverter and gotten rid of quite a few classes in the code base for the project we were working on. This is where my BoolToContentConverter comes in.

Sure, you can also do this with triggers, but if your values keep switching back to their default settings, then you'll need to know a bit about the Dependency Property Value Precedence System that WPF uses to choose the select values of Dependency Properties. I haven't looked at that in a while, but I think there were around seven sources for a property value. You could also do this by coding things into the code behind file, but that kind of defeats the purpose of separating your UI from the rest of your code.  

Background

For this to be useful, you will need to know:

  • How to use converters in your bindings
  • How to use bindings
  • How to use static resources in XAML

The Code

The code for the BoolToContentConverter may look a bit bloated, but it's nothing to be scared of. We just have a class that implements the IValueConverter with three extra properties. These properties will store the content you want to return when given a certain Boolean value.

public class BoolToContentConverter
  : IValueConverter
{
    public BoolToContentConverter()
    {
        TrueContent = "True";
        FalseContent = "False";
        NullContent = "No Value";
    }

    public object TrueContent { get; set; }
    public object FalseContent { get; set; }
    public object NullContent { get; set; }

    public object Convert(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        if (value == null)
            return NullContent;

        bool boolValue = true;
        bool isBool = true;

        try
        {
            boolValue = (bool) value;
        }
        catch
        {
            isBool = false;
        }

        if (!isBool)
            return NullContent;

        return boolValue ? TrueContent : FalseContent;
    }

    public object ConvertBack(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
} 

The BoolToContentConverter can be broken down into three sections:

  • Content properties
    • You have three object type properties that will house the content that will be returned when given a Boolean value. The true and false should be self explanatory, but a beginning programmer might not have much experience with Nullable<T> objects which usually look something like int?, double?, bool?, etc. Some bool type properties are actually bool? type properties, so it's possible they may have a null value, when binding to these guys. That's the reason why there is a NullContent property. 
  • Default values
    • I simple chose default values that I thought were fitting and used the constructor to set them.
  • Conversion method
    • The conversion method can be a bit tricky for two reasons. Someone may have used the converter on a binding source that isn't of either type bool? or bool. And, the source may be null. This is why we have both a null check and a try-catch statement.

Using the Code

Getting a handy piece of code handed over to you is nice and all, but having good examples is even better. Which is why I'm providing you with two examples on using this. One of the nice things about the BoolToContentConverter is that you really can place just about anything in those properties.

<local:BoolToContentConverter x:Key="AcceptedImageConverter"
			  TrueContent="{StaticResource CongratBitmapImage}"
			  FalseContent="{StaticResource ConsolationBitmapImage}"/>

In XAML, large chunks of code can be turned into reusable resources, this can reduce our memory footprint (if placed in the correct location) and make the location they are being used in more readable (they can also make it less readable and a real pain to track down). Here we have two BitmapImage resources being set into the content properties. Like I was saying before, you really can put just about anything into those content properties.

<local:BoolToContentConverter x:Key="ActivatedBrushConverter" NullContent="Black">
	<local:BoolToContentConverter.TrueContent>
		<SolidColorBrush Color="Blue"/>
	</local:BoolToContentConverter.TrueContent>
	<local:BoolToContentConverter.FalseContent>
		<SolidColorBrush Color="Gray"/>
	</local:BoolToContentConverter.FalseContent>
</local:BoolToContentConverter>

In this example, we are creating the content that will be used in the in-line XAML code. I used SolidColorBrushs here because I can create them in a small number of lines, but I could add an ImageBrush to the NullContent property. To be honest, SolidColorBrushes might not be the best example for this because WPF has built in value converters that will convert the string "Black", that is being stored in the NullContent property, into Brushes.Black.

Points of Interest

One of the interesting things I learned when doing this is how powerful the attached converters on those WPF properties can be. This is meant for beginning level developers, so I'm not going to go into any real detail on the attribute system that's used to attached those converters. What I am going to say, is that the Background property on WPF controls has brush converter attached to it. This is the reason why I can start out with something like the string "Black" in the NullContent property and end up with SolidColorBrush when this converter is used in a binding that's targeting a control's Background property. That brush converter is also the reason why we can write "Black" in the Background and Foreground properties of any control and have it use Brushes.Black.

The other thing I learned was to be careful what you place DependencyObjects in those content properties (or in any static resource for that matter). The thing about WPF is that everything that shows up in the VisualTree is a DependencyObject. DependencyObjects can have one and only one parent in their VisualTree placement. Resources allow us to place items in multiple locations in the VisualTree. The reason we can do this, is because a DependencyObject will be used to display the resource, or the resource will be used by a DependencyObject. No matter how many places a resource gets used in the VisualTree, the VisualTree will only consider DependencyObjects as part of the tree.

What I'm trying to get at, is that placing DependencyObjects in the content properties of the BoolToContentConverter will not work out so well if the converter is being used in multiple locations of the VisualTree. I saw this happen with a System.Windows.Controls.Image, and the Image would only show up in the last location that called the converter. This is why we bind the Image's Source property to something like a BitmapImage. I guess you could pull this off having an Image in two locations in the VisualTree if only one location was using that Image it a time. My point is, be careful when using a DependencyObject as a resource.

History

  • Version 1, written by Francisco T. Chavez

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here