可以将TypeConverter用于构造函数参数

时间:2016-01-28 15:12:43

标签: c# wpf xaml typeconverter markup-extensions

我正在尝试写一个像这样的markupextension:

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

要像这样使用:

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

Errs with:

  

“长度”类型的TypeConverter不支持从字符串转换。

如果I:

,TypeConverter可以正常工作
  • 将其放在Value属性上并拥有默认的ctor。
  • 使用属性装饰Length类型。

虽然这可能是x / y,但我不想要任何这些解决方案。

以下是转换器的代码:

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

2 个答案:

答案 0 :(得分:3)

来自MSDN, Applying the TypeConverterAttribute(强调我的):

  

为了将自定义类型转换器用作代理类型   由XAML处理器转换为自定义类,您必须应用   .NET Framework属性TypeConverterAttribute指向类   定义 ...

  

您还可以基于每个属性提供类型转换器。代替   将.NET Framework属性TypeConverterAttribute应用于   类定义,将其应用于属性定义 ...

没有提及任何其他地方来应用该属性。所以你问题的答案很可能是

  

不,TypeConverter不能用于构造函数参数。

答案 1 :(得分:2)

发表此批评:

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

这有效,但我不确定是否有任何缺点。