Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

WPF/WinForms Binding Pt.2: Value converters

In previous WPF vs Windows Forms binding post, we left off with pretty useless text binding example - we made the form's title reflect whatever user writes in the textbox:

<Window x:Class="BindingSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="{Binding ElementName=textBox1, Path=Text}" Height="300" 
Width="300" Loaded="Window_Loaded"> ...
</Window>

public Form1()
{
    InitializeComponent();
    DataBindings.Add("Text", textBox1, "Text");
}

We'll extend this example to make it more flexible about outputting text. How about specifying a text template like "This form now belongs to {0}", where {0} would be replaced with whatever user writes in her textbox? We'll do that with the help of value converters.

To create a value converter in Windows Presentation Foundation, all you have to do is implement the IValueConverter interface:

[ValueConversion(typeof(string), typeof(string))]

public
class TextFormatter:
IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(string)) { throw new ArgumentException("Target type must be string", "parameter"); } return string.Format(parameter.ToString(), value.ToString()); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }

The Convert method takes a couple of parameters: value is the actual value, being passed in by binding, targetType is the type we're binding to, parameter in our case will serve for passing in the text template. We'll ignore culture as we don't need to support different locales at this time. Since we're not supporting converting the text back to initial value, we'll leave ConvertBack method unimplemented.

Next, we'll include our value converter in the binding definition.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="BindingSample.Window1"
    Height="300" Width="300">
    <Window.Resources>
        <local:TextFormatter x:Key="TextFormatter" />
    </Window.Resources>
    <Window.Title>
        <Binding Path="Text" Converter="{StaticResource TextFormatter}" 
            ConverterParameter="This form now belongs to {0}" 
            ElementName="textBox1" Mode="Default"/>
    </Window.Title>

WPF binding with value converter 

Windows Forms, however, doesn't have something like value converters built in, but you can achieve similar result by using custom classes, which implements similar functionality:

public class SimpleTextFormatter: INotifyPropertyChanged
{
    public string parameter;
    private string value;

    public string Parameter
    {
        get { return parameter; }
        set { parameter = value; }
    }

    public string Value
    {
        get { return value; }
        set
        { 
            this.value = value; 
            OnPropertyChanged("Value"); 
        }
    }

    [Bindable(true)]
    public string FormattedText
    {
        get { return string.Format(Parameter, Value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

Using this formatter class is again, very simple. First you have to bind form's Text property to formatter's FormattedText property, then bind the input textbox to it's Value property:

public partial class Form1 : Form
{
    private SimpleTextFormatter formatter = new SimpleTextFormatter();

    public Form1()
    {
        InitializeComponent();
       
        formatter.Parameter = "This form now belongs to {0}";
        DataBindings.Add("Text", formatter, "FormattedText");
        textBox1.DataBindings.Add("Text", formatter, "Value", true, DataSourceUpdateMode.OnPropertyChanged);
    }
        ...
}

Again, no events had to be implemented for this to work, it's just the power of data binding, even when used with Windows Forms.