Can TypeConverter be used for constructor argument

I am trying to write markupextension as follows:

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

Used as follows:

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

Errs with:

TypeConverter for type "Length" does not support conversion from string.

TypeConverter works if I:

  • Put it in the Value property and enter the default ctor value.
  • Decorate the Length attribute with the attribute.

Although it may be x / y, I do not want to make any of these decisions.

Here is the code for the converter:

 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); } } 
+5
source share
2 answers

From MSDN, using TypeConverterAttribute (my highlight):

In order for your custom type converter to be used as a valid type converter for a custom class by the XAML processor, you must apply the .NET Framework TypeConverterAttribute attribute for your class definition ...

and

You can also provide a type converter for each object. Instead of applying the .NET Framework TypeConverterAttribute attribute to the class, apply it to the property definition ...

There is no mention of another place of application of the attribute. So the answer to your question is very likely

No, TypeConverter cannot be used for a constructor argument.

+3
source

Posting this for criticism:

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

This works, but I'm not sure if there are any flaws.

+2
source

Source: https://habr.com/ru/post/1241726/


All Articles