Binding converter as inner class? Binding converter as inner class? wpf wpf

Binding converter as inner class?


I was thinking about this problem again, and I came up with something similar to Dennis's solution : create a "proxy" converter class, with a Type property, which will create the instance of the actual converter and delegate the conversion to it.

public class Converter : IValueConverter{    private Type _type = null;    public Type Type    {        get { return _type; }        set        {            if (value != _type)            {                if (value.GetInterface("IValueConverter") != null)                {                    _type = value;                    _converter = null;                }                else                {                    throw new ArgumentException(                        string.Format("Type {0} doesn't implement IValueConverter", value.FullName),                        "value");                }            }        }    }    private IValueConverter _converter = null;    private void CreateConverter()    {        if (_converter == null)        {            if (_type != null)            {                _converter = Activator.CreateInstance(_type) as IValueConverter;            }            else            {                throw new InvalidOperationException("Converter type is not defined");            }        }    }    #region IValueConverter Members    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        CreateConverter();        return _converter.Convert(value, targetType, parameter, culture);    }    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        CreateConverter();        return _converter.ConvertBack(value, targetType, parameter, culture);    }    #endregion}

You use it like that :

<Window.Resources>    <my:Converter x:Key="CornerRadiusConverter" Type="{x:Type controls:MyPanel+CornerRadiusConverter}"/></Window.Resources>


It could be possible. A few months ago I wrote a markup extension to create the converter for you inline. It keeps a dictionary of weak references so that you don't create multiple instances of the same converter. Handles creating converters with different arguments too.

In XAML:

<TextBox Text="{Binding Converter={NamespaceForMarkupExt:InlineConverter {x:Type NamespaceForConverter:ConverterType}}}"/>

C#:

[MarkupExtensionReturnType(typeof(IValueConverter))]public class InlineConverterExtension : MarkupExtension{  static Dictionary<string, WeakReference> s_WeakReferenceLookup;  Type m_ConverterType;  object[] m_Arguments;  static InlineConverterExtension()  {    s_WeakReferenceLookup = new Dictionary<string, WeakReference>();  }  public InlineConverterExtension()  {  }  public InlineConverterExtension(Type converterType)  {    m_ConverterType = converterType;  }  /// <summary>  /// The type of the converter to create  /// </summary>  /// <value>The type of the converter.</value>  public Type ConverterType  {    get { return m_ConverterType; }    set { m_ConverterType = value; }  }  /// <summary>  /// The optional arguments for the converter's constructor.  /// </summary>  /// <value>The argumments.</value>  public object[] Arguments  {    get { return m_Arguments; }    set { m_Arguments = value; }  }  public override object ProvideValue(IServiceProvider serviceProvider)  {    IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));    PropertyInfo propertyInfo = target.TargetProperty as PropertyInfo;    if (!propertyInfo.PropertyType.IsAssignableFrom(typeof(IValueConverter)))      throw new NotSupportedException("Property '" + propertyInfo.Name + "' is not assignable from IValueConverter.");    System.Diagnostics.Debug.Assert(m_ConverterType != null, "ConverterType is has not been set, ConverterType{x:Type converterType}");    try    {      string key = m_ConverterType.ToString();      if (m_Arguments != null)      {        List<string> args = new List<string>();        foreach (object obj in m_Arguments)          args.Add(obj.ToString());        key = String.Concat(key, "_", String.Join("|", args.ToArray()));      }      WeakReference wr = null;      if (s_WeakReferenceLookup.TryGetValue(key, out wr))      {        if (wr.IsAlive)          return wr.Target;        else          s_WeakReferenceLookup.Remove(key);      }      object converter = (m_Arguments == null) ? Activator.CreateInstance(m_ConverterType) : Activator.CreateInstance(m_ConverterType, m_Arguments);      s_WeakReferenceLookup.Add(key, new WeakReference(converter));      return converter;    }    catch(MissingMethodException)    {      // constructor for the converter does not exist!      throw;    }  }}


What I do is:

<Window.Resources>   <ResourceDictionary>    <Converters:BooleanNotConverter x:Key="BooleanNotConverter"/>   </ResourceDictionary></Window.Resources>

And then in the control

  <CheckBox IsChecked="{Binding Path=BoolProperty, Converter={StaticResource BooleanNotConverter} />