Converters–Part 1–Simple Code-behind Based Converter Tuesday, July 26 2011
Silverlight projects I’ve been a part of tend to develop a robust set of converters. Anything I can do to keep my view model in a relatively pure state (see Part 0 for more details) keeps me happy. However there are times when I also don’t want to write a converter for one simple “throw-away” data conversion. I know I’m not likely to reuse this and I know I also don’t want to change my view model for this one conversion either. Instead, I’ve been using a simple “Code behind converter” where you can specify your conversion code in the code behind of your view.
1: using System;
2: using System.Globalization;
3: using System.Windows.Data;
4:
5: namespace SilverlightApplication5 {
6: public class CodeBehindConverter : IValueConverter {
7: public event EventHandler<ConverterEventArgs> Convert = delegate { };
8: public event EventHandler<ConverterEventArgs> ConvertBack = delegate { };
9:
10: object IValueConverter.Convert( object value, Type targetType, object parameter, CultureInfo culture ) {
11: ConverterEventArgs args = new ConverterEventArgs( value, targetType, culture );
12: Convert( this, args );
13:
14: return args.ConvertedValue;
15: }
16:
17: object IValueConverter.ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) {
18: ConverterEventArgs args = new ConverterEventArgs( value, targetType, culture );
19: ConvertBack( this, args );
20:
21: return args.ConvertedValue;
22: }
23: }
24:
25: public class ConverterEventArgs : EventArgs {
26: public object Value { get; private set; }
27: public object ConvertedValue { get; set; }
28: public CultureInfo Culture { get; private set; }
29: public Type TargetType { get; private set; }
30:
31: public ConverterEventArgs( object value, Type targetType, CultureInfo culture ) {
32: TargetType = targetType;
33: Value = value;
34: ConvertedValue = value;
35: }
36: }
37: }
This converter simply provides a Convert and ConvertBack event that can be handled on the code behind.
For an example of it in use, here is a business entity (which has a status enumeration):
1: namespace SilverlightApplication5 {
2: public class BusinessEntity {
3: public BusinessEnumeration Status { get; set; }
4: }
5:
6: public enum BusinessEnumeration {
7: OperationNotCompleted,
8: OperationPending,
9: OperationWorking,
10: OperationCompleted
11: }
12: }
And here is a view model for a business view:
1: namespace SilverlightApplication5 {
2: public class BusinessViewModel {
3: private BusinessEntity _entity;
4:
5: public BusinessEnumeration Status {
6: get { return _entity.Status; }
7: }
8:
9: public BusinessViewModel() {
10: _entity = new BusinessEntity() {
11: Status = BusinessEnumeration.OperationPending
12: };
13: }
14: }
15: }
And here is the view that displays a friendly version of the status enumeration:
1: <UserControl x:Class="SilverlightApplication5.BusinessView"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: xmlns:local="clr-namespace:SilverlightApplication5">
7: <UserControl.Resources>
8: <local:CodeBehindConverter x:Key="StatusConverter" Convert="ConvertStatus"></local:CodeBehindConverter>
9: </UserControl.Resources>
10: <UserControl.DataContext>
11: <local:BusinessViewModel></local:BusinessViewModel>
12: </UserControl.DataContext>
13: <Grid x:Name="LayoutRoot" Background="White">
14: <TextBlock Text="{Binding Status, Converter={StaticResource StatusConverter}}"></TextBlock>
15: </Grid>
16: </UserControl>
And here is the view’s code behind:
1: using System.Windows.Controls;
2:
3: namespace SilverlightApplication5 {
4: public partial class BusinessView : UserControl {
5: public BusinessView() {
6: InitializeComponent();
7: }
8:
9: private void ConvertStatus( object sender, ConverterEventArgs e ) {
10: switch( (BusinessEnumeration) e.Value ) {
11: case BusinessEnumeration.OperationNotCompleted:
12: e.ConvertedValue = "Not completed";
13: break;
14: case BusinessEnumeration.OperationPending:
15: e.ConvertedValue = "Pending";
16: break;
17: case BusinessEnumeration.OperationWorking:
18: e.ConvertedValue = "Working";
19: break;
20: case BusinessEnumeration.OperationCompleted:
21: e.ConvertedValue = "Complete";
22: break;
23: }
24: }
25: }
26: }
If it turns out you need this elsewhere, it’s easy to change this into its own converter because you followed the same approach as you would have when needing a converter in the first place. Move the code into a custom IValueConverter class and update your usages of this to your new converter.

