Download the example project which includes the source for SwitchConverter and SwitchedContent.
I figured I would write some more about value converters since I think there’s a lot of cool things you can do with them, especially when you put a little extra effort into generalizing them.
One thing I find I need to do often is to show content conditionally depending on a certain data binding condition. For example, let’s say we had a WeatherReport object that had a Condition property that had the following enumeration values: Sunny, Cloudy, Rain, Snow. We want to have a different image for each condition.
In WPF you can do this using a DataTrigger but even that is a bit verbose for my tastes. In Silverlight it’s a lot more difficult. The Expression Blend SDK gives you a behavior called a DataTrigger that can achieve this. But I think a value converter would do this job quite well and the markup will be the same for WPF and Silverlight. Check out the following snippet:
<Grid>
<Grid.Resources>
<e:SwitchConverter x:Key="WeatherIcons">
<e:SwitchCase When="Sunny" Then="Sunny.png" />
<e:SwitchCase When="Cloudy" Then="Cloudy.png" />
<e:SwitchCase When="Rain" Then="Rain.png" />
<e:SwitchCase When="Snow" Then="Snow.png" />
</e:SwitchConverter>
</Grid.Resources>
<Image Source="{Binding Condition, Converter={StaticResource WeatherIcons}}" />
</Grid>
The only thing that was a little bit tricky about this converter was making sure that the value being bound to could be compared against the strings in the When attribute. At first I naively just figured I could "ToString" the input value to the converter and compare that against the When values. But this is very fragile. For example, if the input were a DateTime, the values "6/25/2010" and "6/25/2010 12:00:00 AM" would not be considered equal. That’s not even considering the fact that regional settings would cause even bigger headaches.
So this implementation simply tries to use the IConvertible interface to normalize the values before comparing them. My actual implementation uses a very complex series of checks that take into account available Parse methods, TypeConverter, etc. But it’s a lot of code that I didn’t want to junk up the example with.
The only other thing worth mentioning is that the SwitchConverter has a ContentProperty attribute that allows us to specify the SwitchCase elements inline, making the resulting XAML pretty clean if you ask me. ContentPropertyAttribute is a little known and underused attribute that lets you specify which property will be set by content in between the element tags. There are a lot of places where this should probably be applied such as DataGrid.Columns, Setter.Value, etc. But now I’m going off on a tangent.
So while this solution is in no way a replacement for a good ViewModel, it does let you cleanly represent conditional content in XAML which really sits well with the OCD part of my brain that hates ugly markup.
As a bonus, I’ve also included a SwitchedContent control that makes it much easier to swap out entire elements based upon the conditional input. An example of that is shown below.
<Button Command="{Binding IncrementCommand}">
<e:SwitchedContent Binding="{Binding Count}" Else="Overflow!">
<e:SwitchCase When="0" Then="Zero" />
<e:SwitchCase When="1" Then="One" />
<e:SwitchCase When="2" Then="Two" />
<e:SwitchCase When="3" Then="Three" />
<e:SwitchCase When="4" Then="Four" />
<e:SwitchCase When="5" Then="Five" />
<e:SwitchCase When="6" Then="Six" />
<e:SwitchCase When="7" Then="Seven" />
<e:SwitchCase When="8" Then="Eight" />
<e:SwitchCase When="9" Then="Nine" />
<e:SwitchCase When="10" Then="Ten" />
</e:SwitchedContent>
</Button>
Download the example project which includes the source for SwitchConverter and SwitchedContent.
Thats great, Its such a useful converter. Loved this.
Great! Just what i was looking for!
Thanks!
Awesome, potentially gonna solve a big problem for me!
Thank you
Thanks for this. One note: while SwitchConverter compiles for me in Silverlight, SwitchedContent does not.
This is just beautiful :D thanks so much… saved me loads of time ;)