Click here to Skip to main content
15,867,985 members
Articles / Desktop Programming / WPF

Use of MarkupExtension with Converters in WPF

Rate me:
Please Sign up or sign in to vote.
2.83/5 (13 votes)
14 Apr 2009CPOL2 min read 64.8K   366   12   12
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.

C#
public class NumberToStringConverter : IValueConverter
   {

   }

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

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

We then access this converter in Binding as follows: 

XML
<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:

C#
[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:

XML
<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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
PraiseSolid article, I will use this technique in future Pin
Terry Hutt18-Jun-21 4:46
Terry Hutt18-Jun-21 4:46 
QuestionOverly complex Pin
Clifford Nelson7-Mar-18 9:40
Clifford Nelson7-Mar-18 9:40 
GeneralAlternative approach Pin
Sevenate8-Jun-09 2:29
Sevenate8-Jun-09 2:29 
BugRe: Alternative approach Pin
Clifford Nelson7-Mar-18 9:35
Clifford Nelson7-Mar-18 9:35 
GeneralMy vote of 2 Pin
Kjetil Klaussen20-Apr-09 20:49
Kjetil Klaussen20-Apr-09 20:49 
GeneralGood idea - except it is not a singleton Pin
eug10c14-Apr-09 19:16
eug10c14-Apr-09 19:16 
GeneralRe: Good idea - except it is not a singleton Pin
User-Rock14-Apr-09 19:35
User-Rock14-Apr-09 19:35 
GeneralRe: Good idea - except it is not a singleton Pin
eug10c14-Apr-09 19:53
eug10c14-Apr-09 19:53 
GeneralRe: Good idea - except it is not a singleton Pin
User-Rock14-Apr-09 20:11
User-Rock14-Apr-09 20:11 
Yes, appreciate ur feedback.
but there could be cases where u cant access the Application.Resource, especially when u r working with assembly which is accessed by multiple applications... and the assembly internally requires the Converter in multiple controls...
Is there anything like Application.Resource at assembly level?
GeneralRe: Good idea - except it is not a singleton Pin
eug10c14-Apr-09 20:33
eug10c14-Apr-09 20:33 
GeneralThis link may be useful if you are formatting to string Pin
Lakshmipathy13-Apr-09 20:34
Lakshmipathy13-Apr-09 20:34 
GeneralRe: This link may be useful if you are formatting to string Pin
User-Rock14-Apr-09 2:22
User-Rock14-Apr-09 2:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.