Tips and Tricks: Making Value Converters More Accessible in Markup

I recently had the pleasure of presenting some rather advanced WPF concepts (along with some cool tips and tricks) to a group of smart folks.  Unfortunately, I ran up against time constraints and was forced to drop the data binding portion of my talk.  I’m a little bummed about not being able to show one cool trick that I use a lot, so here it is…

Call me lazy (really, I’m okay with it), but I’ve never been wild about having to declare my value converters as resources before using them.  It’s just one extra step:

<Window.Resources>
  <src:MyConverter x:Key="MyConverter" />
</Window.Resources>

And then later the converter must be specified using a StaticResource reference, which incurs some overhead (albeit small overhead, in the grand scheme of things) for the resource resolution:

<TextBlock Text="{Binding SomePath, Converter={StaticResource MyConverter}}" />

I often choose to skip the middleman.  Instead of using the StaticResource markup extension to look up a converter, I simply derive my value converter, itself, from MarkupExtension.  Then I return an instance of it in the ProvideValue() override.

I have to assume there are plenty of others using this approach too.  (It’s clever, afterall, but that’s about the extent of the hyperbole I’d grant it.)  If you’re not one of them, I simply wanted to put it out there as a potential trick for your arsenal.

Below is a super simple example of a dummy converter (typically used to debug bindings) that does this:

public class DummyConverter : MarkupExtension, IValueConverter
{
    private static DummyConverter _converter = null;
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null)
        {
            _converter = new DummyConverter();
        }
        return _converter;
    }
    #region IValueConverter Members
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return value; // set breakpoint here to debug your binding
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return value;
    }
    #endregion
}

The above class creates a singleton dummy converter that can be used across my app without any resource lookup.  The XAML usage is now simply this:

<TextBlock Text="{Binding SomePath, Converter={src:DummyConverter}}" />

This is much better, to my lazy way of thinking.

14 Responses to “Tips and Tricks: Making Value Converters More Accessible in Markup”

  1. Jacob says:

    Interesting.

    We have a CommonConverters class that exposes static converter instances which we access via the {x:Static xyz:CommonConverters.Foo} markup extension.

  2. Andreas Zenker says:

    Very cool. I love the MarkupExtension twist, I hadn’t thought of that but wish I had.

  3. Rob Burke says:

    Having to declare ValueConverters as Resources never sat well with me either. This is a nice trick. I also look forward to XAML 4.0 taking away some of this pain.

  4. David Nelson says:

    I like it. Could this be made to work with converters that need a parameter?

  5. Dr. WPF says:

    Hi David,

    Do you mean for specifying the ConverterParameter or for supplying a parameter to the constructor of the converter? Both will work, but you’re pretty much stuck with supplying the parameter as a StaticResource (the same as you’d normally do for ConverterParameter) or you could leverage the ObjectReference markup extension I described a while back.

    Cheers,
    -dw

  6. AlanO says:

    Dr. WPF,

    Thank you so much for the great tip!

    I extended it to save one extra step (because I am lazy too) by making an abstract generic class. This makes it easier to convert my existing ValueConverters to use your technique. Sample code follows:

    // Base class
    public abstract class ConverterMarkupExtension: MarkupExtension, IValueConverter
    where T: class, new()
    {
    private static T m_converter = null;

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

    #region IValueConverter Members

    public abstract object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture);
    public abstract object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture);

    #endregion
    }

    //Sample derived class
    public class BytesToKBValueConverter: ConverterMarkupExtension
    {
    public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    if (value != null && value is double)
    {
    double bytes = System.Convert.ToDouble(value);
    return bytes / 1024.0d;
    }
    else
    return value;
    }

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

  7. Eric Burke says:

    We tend to use static instance members (like Jacob) and then reference them as “… Converter={x:Static src:TheFooConverter}”.

    I’m not sure how much overhead subclassing MarkupExtension is, but the bigger issue for me is that I’m also not sure if I would create a new Converter instance every time ProvideValue() is called — think creating 1000 of these as part of a template. Could put a lot of memory pressure on the app without realizing it, and without necessity — generally you only need one converter instance because it’s reused and does not need to be thread-safe.

    I like AlanO’s static approach — best of both worlds.

    For parameterizablility (is that even a word?), the MarkupExtension approach gives you more flexibility because you can create the instance inline as opposed to as a resource or as part of the codebehind. But these situations are rare in my experience.

  8. Dr. WPF says:

    Hi Eric,

    In the example I included above, the converter is a singleton. The markup extension only creates the converter the first time ProvideValue is called and thereafter returns the same instance. Like you say, this works for most converters.

    I, too, like AlanO’s example, which takes my static instance approach and puts it in a base class for easy derivation.

    I do have some examples of per-instance (nonshared) converters that cache object references for performance reasons. I may post an example of one such converter that I think might help others… I did not include it with this article because it requires carefully explaining the usage scenarios so that the same converter is not inadvertently shared across controls. I’ll see what I can write up. :-)

  9. Philipp says:
    Dear Doctor,

    I found the pattern also most helpful when it comes to declaring custom commands – thanks for sharing :-)

    I published the complementing extension here

  10. Dr. WPF says:

    Very cool, Philipp! Nice work! :-D

  11. wekempf says:

    I just discovered this trick, felt stupid for not thinking about it earlier, and figured I’d Google to see how many others had thought of it. That’s when I found this page. It’s a little comforting that the publication date wasn’t that long ago ;) .

    You call this a singleton and say that “the markup extension only creates the converter the first time ProvideValue is called”. That’s not quite accurate. Each time the markup extension is used, a new instance is going to be created, because, well, that’s how markup extensions work. What is true is that only one instance will ever be returned. Use this in a template where it will be used 1000 times, you’ll get 1001 instances constructed, but only 1 of those will not be very shortly garbage collected. It may have some impact on performance, but I doubt you’ll find a scenario where this impact is significant. It won’t have an impact on memory.

    There’s a few alternate implementation ideas to consider. First, you might want to consider using a weak reference instead of a strong reference, just so the “singleton” instance isn’t held longer than it needs to be. If your converter is going to be configurable, you have a couple of choices. You can either cache multiple instances based on the values in the markup extension, or just “return this;” from the ProvideValue (knowing what this will mean to memory usage).

    The {x:Static foo:MyConverter.Instance} alternative isn’t a bad idea, but only works for non-configurable converters, and is more verbose.

  12. Dr. WPF says:

    Yes, you are technically correct, Bill. I should have said there is only a single converter that is “used” for conversions.

    The converter class in this example has no local fields (just methods), so it is very lightweight. Your argument about the class being instantiated repeatedly is valid, but the same thing is true about StaticResource, DynamicResource, etc, and we certainly don’t worry about the perf impacts with these (which are far more prevalent). As such, I’m okay with the overhead.

    But thanks for keeping me honest! :-p

    -dw

  13. Roman says:

    Good tip. But we decided to use Jacob’s approach.
    One tip for all of you who are lazy. You can substitute the

    if (_converter == null)
    {
    _converter = new DummyConverter();
    }
    return _converter;

    part with the following code:

    return _converter ?? (_converter = new DummyConverter());

  14. Yury says:

    If extension is already created and it is also converter we can just “return this;”. It can save us unnecessary ifs, allows base class without template and allows provide additional constructor params specific for instance.
    BTW: x:Static is also MarkupExtension and will be created every time, but inside it has a lot of code.

Leave a Reply