Converters–Part 1–Simple Code-behind Based Converter

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.