DCSIMG
WPF: Where to put value converters? - Arik Poznanski's Blog

Arik Poznanski's Blog

It CAN be done with .NET

News

MVP

MCC

CodeProject MVP

MCPD

MCTS

Subscribe to my blog by email

Arik Poznanski LinkedIn Profile

Email: arik.com at gmail dot com
or, use this form

Locations of visitors to this page


Sela Group

Sela Canada

DZone MVB

Links

Official Blogs

WPF / SL Blogs

Developers Blogs

WPF: Where to put value converters?

The following tip is not new; it is based on this post and its comments.
However, for the sake of completeness and for future reference I bring here the final version.

The question this posts tries to address is: Where to put value converters?

Normal Solution
Usually, the common place to put value converters is in the resources section. With this in place you can use the value converter with StaticResource syntax:

<UserControl.Resources>
    <local:NotConverter x:Key="notConverter" />
</UserControl.Resources>

...

<StackPanel>
    <Button IsEnabled="{Binding Converter={StaticResource notConverter}}" />
</StackPanel>

This means that every time you want to use the value converter you need to add it to the resources section. A better place is to put it in a global converters resource file, so the resource definition is only done once.

Creative Solution
In short, have your converter derive from MarkupExtension. This will avoid the question altogether.
The complete solution provides a generic base class you should derive from, ConverterMarkupExtension. The advantages of deriving from this class are:

  • Your converter can be used as a markup extension. So the former code becomes:
<StackPanel>
    <Button IsEnabled="{Binding Converter={local:notConverter}}" />
</StackPanel>

Specifically, no resource definition is needed. At all.

  • Only one instance of your converter is used to provide the value (sort of singleton).

Note that every time the XAML compiler see a markup extension, it will create a new instance, BUT the following implementation always return the same single converter. If you are worried about all the short lived instances of the markup extension just consider that using StaticResource (another markup extension)would have create them anyway. So there is no additional stress on memory consumption.

  • The base class provide default implementation for both IValueConverter and IMultiValueConverter methods. It throws NotImplementedException. This doesn’t seem much but helps shorten your converter code in the usual case when you implement only one conversion direction.

ConverterMarkupExtension, short version for clarity

public abstract class ConverterMarkupExtension<T> : MarkupExtension, IValueConverter, IMultiValueConverter
        where T : class, new()
    {
        private static T _converter = null;

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

            return _converter;
        }

        #region IValueConverter Members

        public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

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

        #endregion

        #region IMultiValueConverter Members
 
        ...
        
        #endregion

Here you can get the full version of the code including lots of comments.

Using the base class

Following is an example of how to use ConverterMarkupExtension to implement your own converter:

using System;
using System.Windows.Data;
using System.Globalization;

namespace WPF.Common
{
    /// <summary>
    /// Returns the negation of the given boolean value
    /// </summary>
    public class NotConverter : ConverterMarkupExtension<NotConverter>
    {
        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(bool)value;
        }
    }
}

Note that the value converter code remains practically the same, but you get the ability to use it as a markup extension and remove the "not implemented" section.

That’s it for now,
Arik Poznanski.

kick it on DotNetKicks.com Shout it

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# January 28, 2010 2:45 AM

DotNetShoutout said:

Thank you for submitting this cool story - Trackback from DotNetShoutout

# January 28, 2010 2:46 AM

WPF: Where to put value converters? – Arik Poznanski's Blog | Drakz Free Online Service said:

Pingback from  WPF: Where to put value converters? &#8211; Arik Poznanski&#039;s Blog | Drakz Free Online Service

# January 29, 2010 9:41 AM

WPF: Where to put value converters? - Arik Poznanski's Blog Mobile said:

Pingback from  WPF: Where to put value converters? - Arik Poznanski&#39;s Blog Mobile

# January 29, 2010 1:00 PM

Jmix90 said:

Very, very , very interesting and useful : thanks a lot !

# January 29, 2010 1:03 PM

WPF_Clown said:

Hi Arik,

I read the article and it's great, but something is bugging me, using your converter method I need to rewrite all my converters and also whenever I want to use a converter from the net I will need to change it.

Why not using the same technique but with reflection and then whenever I use a converter I just insert the converter type to the markup extension?

# July 8, 2010 6:47 PM

arik said:

I think the syntax for using the converter might get a bit more complex.

Anyway, that's an interesting idea.

# July 12, 2010 11:55 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: