Click here to Skip to main content
Licence CPOL
First Posted 30 Mar 2010
Views 7,692
Bookmarked 11 times

Quick WPF tip: Generic Converter MarkupExtension

By | 24 Apr 2010 | Technical Blog
Quick WPF tip: Generic Converter MarkupExtension
A Technical Blog article. View original blog here.[^]

Hey there!

It’s been quite a while since the last English post – XAMLCast has been taking much of my blogging time. :-)

Today’s tip is an expansion of a method originally developed by Dr. WPF in this post: http://www.drwpf.com/blog/Home/tabid/36/EntryID/48/Default.aspx.

Usually, when working with Converters in WPF/SL, we always follow the same steps:

  1. Create a class that derives from IValueConverter:
    public MyConverter : IValueConverter {}
  2. Implement Convert (and sometimes ConvertBack):
    public object Convert(object value, Type  targetType, 
    	object parameter,  System.Globalization.CultureInfo culture)
    {
      // convert and return something
    }
  3. Instantiate the converter as a resource and use it:
    <ResourceDictionary ...>
        <local:MyConverter x:Key="TheConverter" />
    </ResourceDictionary>
    ...
    {Binding Converter={StaticResource TheConverter} ...}

Well, it works but it’s not a compact syntax. Following Dr. WPF’s idea, we can use a MarkupExtension to replace the StaticResource by a static instance of the Converter:

public class  MyConverter: MarkupExtension, IValueConverter
{
    private static MyConverter _converter;

    public object Convert(object  value, Type targetType, 
	object  parameter, System.Globalization.CultureInfo culture)
    {
        // convert and return something
    }

    public object  ConvertBack(object value, Type  targetType, 
	object parameter,  System.Globalization.CultureInfo culture)
    {
        // convert and return something (if needed)
    }

    public override object  ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null)
            _converter = new MyConverter();
        return _converter;
    }
}

Usage:

xmlns:conv="[Path to namespace that contains the converter]"
...
{Binding Converter={conv:MyConverter}}

Now that’s pretty!

The only problem is that with this method, you'd have to repeat the implementation of the ProvideValue for each converter you create, and we programmers hate repeating ourselves. :-)

One solution I found is to create a generic abstract class that will contain that implementation, and derive each converter from that class. It’s cleaner and works the same:

using System;
using System.Windows.Data;
using System.Windows.Markup;

namespace VirtualDreams.Converters
{
    [MarkupExtensionReturnType(typeof(IValueConverter))]
    public abstract class ConverterMarkupExtension<T> : 
	MarkupExtension where T : class, IValueConverter, new()
    {
        private static T _converter;

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (_converter == null)
            {
                _converter = new T();
            }
            return _converter;
        }
    }
}

Let’s apply it to MyConverter:

public class  MyConverter: ConverterMarkupExtension<MyConverter>, IValueConverter
{
    public object Convert(object  value, Type targetType, 
	object  parameter, System.Globalization.CultureInfo culture)
    {
        // convert and return something
    }

    public object  ConvertBack(object value, Type  targetType, 
	object parameter,  System.Globalization.CultureInfo culture)
    {
        // convert and return something (if needed)
    }
}

Usage:

xmlns:conv="[Path to namespace that contains the converter]"
...
{Binding Converter={conv:MyConverter}}

Simpler, less repetitive – that’s the way I like it!

Happy converting!

Roberto

This blog post is also available on

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Roberto Sonnino


Virtual Dreams
Brazil Brazil

Member

Follow on Twitter Follow on Twitter
Hi! I'm Roberto. I'm a Brazilian Engineering student at the University of São Paulo and the Ecole Centrale de Lille (France).
 
I've participated in the Imagine Cup competition and went to the world finals every year from 2005 to 2009. I also won the 1st place award in 2006, in India, for the Interface Design invitational, in 2007 in Korea, for the Embedded Development invitational, and in 2009 in Egypt for the Windows Mobile Award.
 
Currently I keep a blog (in English and Portuguese) at http://virtualdreams.com.br/blog/ and a weekly webcast about WPF and Silverlight (in Portuguese) at http://www.xamlcast.net.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionShorter Pinmemberhennsamc10:23 5 Aug '11  
GeneralNot applicable to Silverlight (up to and including v4) PinmemberSidhe10:19 24 Apr '10  
GeneralRe: Not applicable to Silverlight (up to and including v4) PinmemberRoberto Sonnino10:49 24 Apr '10  
GeneralThanks PinmemberMetaEM20:48 5 Apr '10  

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

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 24 Apr 2010
Article Copyright 2010 by Roberto Sonnino
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid