2016-01-28 11 views
5

ich eine Markupextension so zu schreiben bin versucht:Kann ein Typeconverter für Konstruktorargument verwendet werden

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

Errs mit:

[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; 
    } 
} 

Um wie folgt verwendet werden

Der TypeConverter für den Typ "Length" unterstützt keine Konvertierung von String.

Die Typeconverter funktioniert, wenn ich:

  • es auf der Value Eigenschaft Put und einen Standard Ctor haben.
  • Dekorieren Sie den Typ Length mit dem Attribut.

Während dies x/y sein kann, möchte ich keine dieser Lösungen. Hier

ist der Code für den Konverter:

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); 
    } 
} 

Antwort

3

Von MSDN, Applying the TypeConverterAttribute (Hervorhebung von mir):

Damit Ihr Konverter benutzerdefinierten Typ von einem XAML-Prozessor für eine benutzerdefinierte Klasse, die als Wirkend -Wandler verwendet werden, können Sie die .NET Framework anwenden müssen Attribut Typeconverter auf Ihre Klasse Definition ...

und

Sie können auch einen Typkonverter pro Eigenschaft bereitstellen. Stattdessen ein .NET Framework-Anwendung von Typeconverter auf die Klassendefinition Attribut, es auf eine Eigenschaft Definition ...

Keine Erwähnung von jedem anderen Ort, um das Attribut anzuwenden. So ist die Antwort auf Ihre Frage sehr wahrscheinlich

Nein, ein TypeConverter kann nicht für ein Konstruktorargument verwendet werden.

+0

Vielen Dank mein Herr, ich scheitere beim googeln. Wissen Sie, wie viel implizite Konvertierung das Attribut auf die Klassendefinition anwendet? Vielleicht ist das eine andere Frage. Oder vielleicht [chat] (http://chat.stackoverflow.com/rooms/18165/wpf) –

+0

Nicht sicher, was "wie viel implizite Konvertierung" eigentlich bedeutet. Wenn Sie jedoch das Attribut auf den Length-Typ anwenden, findet die Konvertierung immer dann statt, wenn Sie eine Länge in XAML festlegen. – Clemens

+0

Stellt sich heraus, Bindungen verwendet es auch. Vielleicht Sachen wie Serialisierung. Ich bin kein großer Fan von impliziter Konvertierung :) –

2

dieses Posting für Kritik:

[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; 
    } 
} 

Dies funktioniert, aber ich bin nicht sicher, ob es irgendwelche Nachteile sind.