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

Use of MarkupExtension with Converters in WPF

0.00/5 (No votes)
14 Apr 2009 1  
Optimize converters in WPF with MarkupExtension

Introduction 

Software is required to represent display components with different values than one used for storing. WPF provides the feature of Converter(IValueConverter/IMultiValueConverter) to do such conversion with ease. We will see how to use converters and the optimum way of accessing the converters using MarkupExtension.

Background

Markup Extension is a built in feature provided by WPF framework for extending XAML. Markup extension is defined within curly braces ({}).
Few Inbuilt extensions provided by WPF framework are:

  • BindingExtension
  • StaticResourceExtension
  • DynamicResourceExtension
  • RelativeSourceExtension
  • StaticExtension
  • TypeExtension

Just like Dependency property or attributes, we don't need to write the word ‘extension’ when accessing it in XAML. 

Using the Code

The article is primarily divided into two parts as follows:

  1. Use of Converter in WPF 
  2. Use of MarkupExtension to optimize the construction of Converter

Note: The following example is used only for demonstrating the concept.

Use of Converter in WPF Application

Converters are used in WPF to convert the value of one data type to another. Or in simple language, Converter (class inheriting IValueConverter) accepts value in one format and returns the value in another format.

 public class NumberToStringConverter : IValueConverter
    {

    }

In order to access this converter, we declare a resource in XAML. E.g.

<Window.Resources>        
    <local:NumberToStringConverter x:Key="numConverter"></local:NumberToStringConverter>
</Window.Resources>

We then access this converter in Binding as follows: 

<TextBox x:Name="txtBox1">100</TextBox>
<TextBox Text="{Binding Path=Text,Converter=
		{StaticResource numConverter},ElementName=txtBox1}" >

This is a simple example demonstrating converter usage. If we require converter in different XAMLs, we repeat the above code in each one of them.

Now if you look carefully, this is redundant coding. We will end up having n number of instances of a converter. Don't you think converters are meant to convert value of one type to other? So do we really require creating n number of instances of one converter class?

Use of MarkupExtension with Singleton in Creating Converters

We can utilize the inbuilt feature of WPF to remove this redundancy. WPF provides MarkupExtension to access your custom object in XAML. WPF MarkupExtension allows us to write converters in an optimized way. Let’s see how.

In the above case, we can access the converter instance in XAML without creating its resource instance. To allow this, the Converter has to be inherited from MarkupExtension.
MarkupExtension is an abstract class defined by WPF Framework. We need to override ProvideValue method. ProvideValue method accepts variable of type IServiceProvider (again a framework declared interface). We can use this method to return a singleton instance of Converter as:

[MarkupExtensionReturnType(typeof(IValueConverter))]
public class NumberToStringConverterExtension: MarkupExtension, IValueConverter
{
    private static NumberToStringConverterExtension _converter;
     public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null)
        {
            _converter = new NumberToStringConverterExtension();
        }
        return _converter;
    }
     #region IValueConverter Members
     public object Convert(object value, Type targetType, 
	object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
        {
            return Binding.DoNothing;
        }
        return GetString(value);
    }
     public object ConvertBack(object value, Type targetType, 
	object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null && !string.IsNullOrEmpty(value.ToString()))
        {
            return GetInt(value);
        }
        return 0;
    }
     #endregion
     private string GetString(object value)
    {
        //Some logic to convert int to string..
        return value.ToString();
    }
     private int GetInt(object value)
    {
       //Some logic to convert string to int..
       int val;
       int.TryParse(value.ToString(), out val);
       return val;
    } 
}

We can use this singleton instance in XAML as follows:

<TextBox x:Name="txtBox1">100        
<TextBox Text="{Binding Path=Text,Converter=
	{local:NumberToStringConverter},ElementName=txtBox1}">

Note: In the above code snippet, you can find that NumberToStringConverter extension object is accessed without writing Extension suffix.

Points of Interest  

Inheriting converters with MarkupExtension allows developers to access the Converter directly in XAML without declaring it as Resource. Again as converters are used for generic activity, the instance can be made singleton restricting the user from creating more than one instance.

History

  • First version - 14 April 2009 - Explains use of MarkupExtension to access Converter as WPF extension

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