2016-01-28 8 views
5

Sto cercando di scrivere un MarkupExtension come questo:Può un TypeConverter essere utilizzato per argomento del costruttore

[MarkupExtensionReturnType(typeof(Length))] 
public class LengthExtension : MarkupExtension 
{ 
    // adding the attribute like this compiles but does nothing. 
    public LengthExtension([TypeConverter(typeof(LengthTypeConverter))]Length value) 
    { 
     this.Value = value; 
    } 

    [ConstructorArgument("value")] 
    public Length Value { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this.Value; 
    } 
} 

Per essere utilizzato in questo modo:

<Label Content="{units:Length 1 mm}" /> 

sbaglia con:

Il TypeConverter per il tipo "Length" non supporta la conversione da stringa.

Il TypeConverter funziona se:

  • Metterlo sulla proprietà Value e hanno un ctor di default.
  • Decorare il tipo Length con l'attributo.

Mentre questo può essere x/y non voglio nessuna di quelle soluzioni.

ecco il codice per il convertitore:

public class LengthTypeConverter : TypeConverter 
{ 
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     if (sourceType == typeof(string)) 
     { 
      return true; 
     } 

     return base.CanConvertFrom(context, sourceType); 
    } 

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
    { 
     if (destinationType == typeof(InstanceDescriptor) || destinationType == typeof(string)) 
     { 
      return true; 
     } 

     return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     var text = value as string; 
     if (text != null) 
     { 
      return Length.Parse(text, culture); 
     } 

     return base.ConvertFrom(context, culture, value); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
    { 
     if (value is Length && destinationType != null) 
     { 
      var length = (Length)value; 
      if (destinationType == typeof(string)) 
      { 
       return length.ToString(culture); 
      } 
      else if (destinationType == typeof(InstanceDescriptor)) 
      { 
       var factoryMethod = typeof(Length).GetMethod(nameof(Length.FromMetres), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(double) }, null); 
       if (factoryMethod != null) 
       { 
        var args = new object[] { length.metres }; 
        return new InstanceDescriptor(factoryMethod, args); 
       } 
      } 
     } 

     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 

risposta

3

Da MSDN, Applying the TypeConverterAttribute (sottolineatura mia):

Affinché il convertitore di tipo personalizzato da utilizzare come tipo di recitazione convertitore per una classe personalizzata da un processore XAML, è necessario applicare il Framework .NET attribuire TypeConverterAttribute al tuo classe definizione ...

e

È inoltre possibile fornire un convertitore di tipi per ogni proprietà. Invece di applicare un .NET Framework attribuiscono TypeConverterAttribute alla definizione di classe, applicarlo ad una definizione proprietà ...

Nessuna menzione di qualsiasi altro luogo per applicare l'attributo. Quindi la risposta alla tua domanda è molto probabile

No, un TypeConverter non può essere utilizzato per un argomento del costruttore.

+0

Grazie signore, non riesco a cercare su Google. Ti capita di sapere quanta conversione implicita applica l'attributo alla causa della definizione di classe? Forse questa è un'altra domanda. O forse [chat] (http://chat.stackoverflow.com/rooms/18165/wpf) –

+0

Non sai cosa significhi "Quanta conversione implicita". Ma se si applica l'attributo al tipo Lunghezza, la conversione avverrà ogni volta che si imposta una lunghezza in XAML. – Clemens

+0

Anche i collegamenti estesi lo utilizza. Forse cose come la serializzazione. Non sono un grande fan della conversione implicita :) –

2

questo distacco per la critica:

[MarkupExtensionReturnType(typeof(Length))] 
public class LengthExtension : MarkupExtension 
{ 
    public LengthExtension(string value) 
    { 
     this.Value = Length.Parse(value, CultureInfo.InvariantCulture); 
    } 

    public Length Value { get; private set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this.Value; 
    } 
} 

Questo funziona, ma io non sono sicuro di se ci sono aspetti negativi.

Problemi correlati