Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Custom Value Conversion in WPF

0.00/5 (No votes)
24 Apr 2013 1  
This article describes how to perform custom value conversions in WPF.

Introduction

In WPF, custom value converters can be used to convert data from one type to another. A custom converter can be used to implement custom logic to convert one value to another. To demonstrate this article, I have developed an application in Visual C# 2010 Express Edition, that takes a decimal value as input and converts it into binary, octal, and hexadecimal values.

Background

To create a custom converter, we need to implement the IValueConverter interface in our user-defined converter class. The IValueConverter interface has two methods which we must implement in our class. These methods are as follows:

  • Convert: This method converts a source value to target. This method's signature is as follows:
  • public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    In this method we code the logic for our custom conversion.

  • ConvertBack: This method converts a value back from target to source. This method's signature is same as the Convert method. We can avoid writing custom code in this method if we do not want to convert a value back to source.

Using the Code

The following XAML code is used to define the user interface of our application:

<Window x:Class="NumberSystemConversion.MainWindow"        
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:NumberSystemConversion"
        Background="BlanchedAlmond"
        Title="Number System Converter" Height="350" Width="600">
    <Window.Resources>
        <local:NumberSystemConverter x:Key="myConverter"/>
    </Window.Resources>
    <Canvas>
        <Label Canvas.Left="100" Canvas.Top="10" FontFamily="Comic Sans MS" 
               FontSize="32" Foreground="Fuchsia">Number System Converter</Label>
        <Label Canvas.Left="40" Canvas.Top="100" FontFamily="Aharoni" FontSize="24" 
               Foreground="BlueViolet">Enter a Decimal Number: </Label>
        <TextBox Name="txtDecimal" Canvas.Left="330" Canvas.Top="100" Width="225" 
               FontFamily="Aharoni" FontSize="24" 
               Foreground="BlueViolet" Background="LightPink"/>
        <Label Canvas.Left="220" Canvas.Top="150" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Red">Binary:</Label>
        <TextBlock Name="txtBinary" Canvas.Left="330" Canvas.Top="150" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Red" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=2}"/>
        <Label Canvas.Left="233" Canvas.Top="200" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Green">Octal:</Label>
        <TextBlock Name="txtOctal" Canvas.Left="330" Canvas.Top="200" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Green" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=8}"/>
        <Label Canvas.Left="147" Canvas.Top="250" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Blue">Hexadecimal:</Label>
        <TextBlock Name="txtHexadecimal" Canvas.Left="330" Canvas.Top="250" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Blue" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=16}"/>
    </Canvas>
</Window>

In the above code, I have created a window resource called myConverter which points to our custom converter class called NumberSystemConverter. A TextBox called txtDecimal is used to accept a number to be converted. Three TextBlocks: txtBinary, txtOctal, and txtHexadecimal are used to display the converted results. The three TextBlocks are bound to the txtDecimal TextBox using element binding. The converter NumberSystemConverter is used to convert the decimal number to binary, octal, and hexadecimal using the Converter property. The ConverterParameter property is used to specify the target type as 2, 8, and 16 for converting to binary, octal, and hexadecimal values, respectively.

Following is the code of our Number System Converter:

public class NumberSystemConverter : IValueConverter
{
    Stack<object> stack = new Stack<object>();
    public object Convert(object value, Type targetType, object parameter, 
                  System.Globalization.CultureInfo culture)
    {
        // Store result digits in array
        object[] digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F" };
        try
        {
            // Get the source value
            int number = System.Convert.ToInt32(value.ToString());
            if (number == 0)
            {
                return 0;
            }
            // Get the target number system
            int divisor = System.Convert.ToInt32(parameter.ToString());
            while (number > 0)
            {
                int remainder = number % divisor;
                // Push digits to stack
                stack.Push(digits[remainder]);
                number /= divisor;
            }
            StringBuilder builder = new StringBuilder();
            while (stack.Count > 0)
            {
                builder.Append(stack.Pop().ToString());
                // Return digits in LIFO order
            }
            return builder.ToString();
            // Return result
        }
        catch (Exception)
        {
            return null;
        }
    }
    public object ConvertBack(object value, Type targetType, object parameter, 
                  System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

In the above code, the first parameter of the Convert method represents the number to be converted (number) and the third parameter represents the target number system (divisor). The number is divided by the divisor and the remainder is pushed into a stack. At the end, the numbers are popped out of the stack and appended to a StringBuilder object. The StringBuilder is converted to String and returned as the result to be displayed on the target TextBlock.

The ConvertBack method is not required to be implemented.

Points of Interest

Though there are many more uses of converters and a variety of ways of using converters, I hope that the above discussion would help in understanding the working of converters in WPF.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here