This is OK but it’s fairly verbose and leads to converters being defined all over the place. An alternative is to use a MarkupExtension to minimize the amount of XAML code required. E.g.:
public class AdditionConverter : MarkupExtension, IValueConverter
{
private static AdditionConverter _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 AdditionConverter();
return _converter;
}
}
Doing this you no longer need to define a resource as the XAML parser knows how to ask the markup extension to supply the converter. You end up with a syntax like this:
{Binding Converter={conv:MyConverter}}
This approach has an added advantage of ensuring that all your converters are singletons.
Taking it further: Making a wrapper base class
This article explains a generic markup extension class that hides the MarkupExtension implementation details and makes the process above even easier.
This article explains a generic markup extension class that hides the MarkupExtension implementation details and makes the process above even easier.
ConverterMarkupExtension.cs
using System;
using System.Windows.Data;
using System.Windows.Markup;
namespace sfc.Converters
{
[MarkupExtensionReturnType(typeof(IValueConverter))]
public abstract class ConverterMarkupExtension :
MarkupExtension where T : class, IValueConverter, new()
{
private static T _converter;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
{
_converter = new T();
}
return _converter;
}
}
[MarkupExtensionReturnType(typeof(IMultiValueConverter))]
public abstract class MultiConverterMarkupExtension :
MarkupExtension where T : class, IMultiValueConverter, new()
{
private static T _converter;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
{
_converter = new T();
}
return _converter;
}
}
}
There are 2 classes here, one for IValueConverter's and one for IMultiValueConverters.
You can then modify your classes to inherit from this class and they nolonger need to worry about implementing MarkupExtension E.g.:
You can then modify your classes to inherit from this class and they nolonger need to worry about implementing MarkupExtension E.g.:
public class AdditionConverter : ConverterMarkupExtension<AdditionConverter>
{
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)
}
}
No comments:
Post a Comment