Originally published on my old Charteris blog
As I said before WPF data binding, along with the various types of triggers, helps keep the minutiae of UI logic out of your “code behind”. I am amazed by what can be done with just XAML, I was fortunate enough to have a conversation with one of the Microsoft Max team a few weeks back and they he was very keen to explain how much can be done in just XAML.
Therefore I try hard, very hard to keep my UI to XAML but sometimes the binding XML is just too simplistic. Imagine this, I am running a UK region Windows OS with UK settings as default, my UI culture is en-GB and my SQL Server is all UK’ed up. I databound to the DateOfBirth property of my person object to find that the WPF would only display the date in US format arrrrggggghhhhhhhh!!!! I know that Microsoft is a US company but their continual defaulting to US formats is annoying.
<TextBlock HorizontalAlignment="Center" Text="{Binding Path=DateOfBirth}"/>
Simple binding to the DateOfBirth property where the DataContext of the TextBlock was an instance of Person
The solution to this situation and any where your binding needs a little help from some good old-fashioned code is a Converter. There are two types of Converters IValueConverter and IMultiValueConveter, IValueConverter is used to convert a single data value to another whereas a MultiValueConveter is used to convert multiple data values to a single value. Both interfaces support two-way binding with the Convert and ConvertBack methods.
<TextBlock HorizontalAlignment="Center"
Text="{Binding Path=DateOfBirth, Converter={StaticResource MyDateToShortDateStringConverter}}"/>
Here the TextBlock XAML has changed to include a reference to the converter.
The Convert method simply formats the date to the UK format we required. The display of the UK date was read only so I only needed to worry about Convert, returning Binding.DoNothing (I love that naming) from ConvertBack.
public object Convert(object dataValue, Type type,
object parameter, CultureInfo culture)
{
DateTime date = (DateTime)dataValue;
return string.Format("{0:ddd-MMM-YYYY}", date);
}
One really useful converter that ships with WPF is the BooleanToVisibilityConverter. This simply takes a bound boolean data value and converts it to either Visibility.Collapsed (False) or Visibility.Visible(True) . If the simple databing example from a previous post, we can get bind the Visibility of a section of the UI to the IsChecked property of the ToggleButton.
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300">
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter"/>
</Grid.Resources>
<StackPanel Background="Green">
<ToggleButton Content="Hide/Show" Margin="5" Name="HideShowButton" IsChecked="True"/>
<Border BorderThickness="0.5" BorderBrush="AntiqueWhite" Margin="5"
Visibility="{Binding ElementName=HideShowButton, Path=IsChecked,
Converter={StaticResource BoolToVisConverter}}">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="First Name" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="0"/>
<TextBox Grid.Row="0" Grid.Column="1"/>
<Label Content="Last Name" HorizontalAlignment="Right" Grid.Row="1" Grid.Column="0" />
<TextBox Grid.Row="1" Grid.Column="1"/>
</Grid>
</Border>
</StackPanel>
</Grid>
It's getting late now and I need rest so time to go to bed, perhaps tomorrow we will meet IMultiValueConverter...