2009-05-14 27 views
8

バインディングコンバータを使用するUserControlがあります。私はコンバータを内部クラスにしました内部クラスとしてバインディングコンバータ?

public partial class MyPanel : UserControl 
{ 
    public class CornerRadiusConverter : IValueConverter 
    { 

どのようにしてConverterクラスをXAMLから参照しますか?以下は動作しません:

<controls:MyPanel.CornerRadiusConverter x:Key="CornerRadiusConverter" /> 

それは、このエラーを与える:

The tag 'LensPanel.CornerRadiusConverter' does not exist in XML namespace 'clr-namespace:MyApp.Windows.Controls'

+0

は、通常のクラスを使用します! –

+2

@ SergeyAldoukhov:なぜですか?その提案は役に立たない。 –

答えて

2

私はこの問題についてもう一度考えていましたが、Dennisのソリューションに似たものを思いつきました。実際のコンバータのインスタンスを作成して変換を委譲するTypeプロパティを持つ "プロキシ"コンバータクラスを作成します。

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 
} 

あなたはそのようにそれを使用します。

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

ことが可能である可能性があります。数か月前に、私はあなたのインラインのコンバータを作成するためのマークアップ拡張を書きました。同じコンバータの複数のインスタンスを作成しないように、弱い参照の辞書を保持します。引数の異​​なるコンバータも作成します。 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; 
    } 
    } 

} 
+0

素晴らしいアイデア!私は自分自身のカスタムマークアップ拡張の大きなファンです;​​) –

-3

私は何をすることです:

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

そして制御で

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

彼のコンバータクラスはネストされたクラスであることは、ロバートの問題を解決しません... –

関連する問題