How do I bind to the opposite of a value?
A coworker came to me the other day and asked how she could enable a textbox when a particular
radio button was not selected. The problem she noted is that she couldn't directly bind the Textbox.IsEnabled property to the
RadioButton.IsChecked property. What she really wanted to do was bind IsEnabled to !IsChecked.
I took this opportunity to introduce her to the concept of value converters. As the name implies, a value converter
converts one type (the source) to another (the target). Value converters are used heavily in WPF because XAML attributes
are strings, but these strings need to be converted into objects. For instance, the string value of "red" for a background in XAML
needs to be converted to a Color object representing red (eg. Color.Red).
This article introduces the concept of value converters by exploring a solution to the problem of how to bind to the
opposite boolean value of a property.
Creating a Custom Converter
To create a custom converter, simply create a class implementing the System.Windows.Data.IValueConverter interface. This interface
defines two methods:
- Convert - converts source to target
- ConvertBack - converts target to source, used for two-way databinding
For one-way databinding, you only need to implement the Convert method, which is what I did below. All that the Convert
method does is return the opposite boolean value that was passed in.
public class BoolToOppositeBoolConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
Using a Custom Converter
Once you have your custom converter, the next step is to use that within a binding expression. For my demo, I imported
the namespace of my converter (line 4), and created an instance as a resource (line 7). I then used the converter in the
binding expression for my textbox (lines 14-15) by adding
Converter={StaticResource oppositeConverter}}. That's it.
1 <Window x:Class="OppositeValueConverterDemo.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:wpfdude="clr-namespace:OppositeValueConverterDemo.Converters"
5 Title="Window1" Height="150" Width="200" >
6 <Window.Resources>
7 <wpfdude:BoolToOppositeBoolConverter x:Key="oppositeConverter" />
8 </Window.Resources>
9 <StackPanel Margin="10,10,10,10">
10 <RadioButton IsChecked="True" Height="20" Name="radRed">Red</RadioButton>
11 <RadioButton Height="20" Name="redYellow">Yellow</RadioButton>
12 <RadioButton Height="20" Name="redGreen">Green</RadioButton>
13 <TextBox Height="21" Width="150" Name="textBlock1" Text="Sample Text"
14 IsEnabled="{Binding ElementName=radRed, Path=IsChecked,
15 Converter={StaticResource oppositeConverter}}" />
16 </StackPanel>
17 </Window>
Download Sample Solution
I put together a simple solution with three radio buttons and a textbox. When the Red radio button is selected, the textbox
is disabled. When either of the other two radio buttons are enabled, the textbox is enabled.
Download the sample solution here