IValueConverter with Markup Extension

We have seen the Introduction to Value Converters in the previous post.  Converter is a Binding property of type IValueConverter. You can set this property to an instance of a class which implements that interface to intercept any movement of data from the binding source to the binding target, or vice versa. Value converters are very convenient and are used quite often.  If you want to use a normal ValueConverter in XAML, you have to add an instance of it to the resources and reference it by using a key. To learn more about instantiating an object as a resource in XAML, see the post. This is cumbersome, because and the key is typically just the name of the converter or you can derive your value converter from MarkupExtension and return its own instance in the ProvideValue override. So you can use it directly without referencing it from the resources.

public override object ProvideValue(IServiceProvider serviceProvider)
{
    throw new NotImplementedException();
}

So to enhance our experience with converters,  derive value converters from MarkupExtension. This way you can create and use it in the binding like this: Text={Binding studentname, Converter={x:MyConverter}}

Following are the steps to create a converter with Markup extension.

  1. Import namespace
    using System.Windows.Markup;

  2. Derive our class from MarkupExtension, IValueConverter
    public class ScoreToColorConverter : MarkupExtension, IValueConverter

  3. Override the ProvideValue method of MarkupExtension class and return this
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

  4. Implement the IValueConverter interface methods Convert & ConvertBack
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string s = (string) value;
        if (Int32.Parse(s) <= 35)
            return new SolidColorBrush(Colors.Red);
        else
            return new SolidColorBrush(Colors.Green);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

  5. Specify the xmlns:XXXX in the Window XAML tag
    xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"

  6. Specify the UI elements and mention the binding properties. Notice here that we are specifying the Binding converter property as Converter={MyXAMLClass:ScoreToColorConverter}, which is a simple and decent implementation.
    <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
     <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>

The complete XAML is:

<Window x:Class="DataBinding_MultiConverter2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"
        >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
        <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>
    </Grid>
</Window>

The complete source code of the classes used is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;

namespace DataBinding_MultiConverter2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class ScoreToColorConverter : MarkupExtension, IValueConverter
    {

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string s = (string) value;
            if (Int32.Parse(s) <= 35)
                return new SolidColorBrush(Colors.Red);
            else
                return new SolidColorBrush(Colors.Green);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Download the Source code from here. Default conversions may be available because of type converters that are present in the type being bound to. This behavior will depend on which type converters are available in the target. If in doubt, create your own converter.

Following are some typical scenarios where it makes sense to implement a data converter:

  • Your data should be displayed differently, depending on culture. For instance, you might want to implement a currency converter or a calendar date/time converter based on the values or standards used in a particular culture.

  • The data being used is not necessarily intended to change the text value of a property, but is instead intended to change some other value, such as the source for an image, or the color or style of the display text. Converters can be used in this instance by converting the binding of a property that might not seem to be appropriate, such as binding a text field to the Background property of a table cell.

  • More than one control or to multiple properties of controls are bound to the same data. In this case, the primary binding might just display the text, whereas other bindings handle specific display issues but still use the same binding as source information.

  • In the case of a MultiBinding, where a target property has a collection of bindings, you use a custom IMultiValueConverter to produce a final value from the values of the bindings. For example, color may be computed from red, blue, and green values, which can be values from the same or different binding source objects.

See Introduction to Value Converters in the previous post

Download the Source code from here

In organizations, real power and energy is generated through relationships. The patterns of relationships and the capacities to form them are more important than tasks, functions, roles, and positions. –Margaret Wheatley
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s