5

我想为自定义类型Thickness 实现TypeConverter。我查看了微软发布的类型转换器,如SizeConverter

当我键入一个字符串或更改我的厚度属性上的一个属性时,设计器会使用它,它只是不会将更改保存到“Designer.cs”。它必须是从类型“Thickness”到“InstanceDescriptor”的转换,但我找不到我的代码有什么问题......

这里是Thickness

[TypeConverter(typeof(ThicknessConverter))]
public struct Thickness
{
    Double top;
    Double bottom;
    Double right;
    Double left;

    public Thickness(Double uniformLength)
    {
        top = uniformLength;
        bottom = uniformLength;
        right = uniformLength;
        left = uniformLength;
    }

    public Thickness(Double left, Double top, Double right, Double bottom)
    {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }
    public Double Top
    {
        get { return top; }
        set { top = value; }
    }
    public Double Bottom
    {
        get { return bottom; }
        set { bottom = value; }
    }
    public Double Right
    {
        get { return right; }
        set { right = value; }
    }
    public Double Left
    {
        get { return left; }
        set { left = value; }
    }
    public Double UniformLength
    {
        get
        {
            if (!IsUniform)
                throw new InvalidOperationException();
            else return top;
        }
        set
        {
            top = value;
            bottom = value;
            right = value;
            bottom = value;
        }
    }
    public Boolean IsUniform
    {
        get { return top == bottom && bottom == right && bottom == left; }
    }
}

这是类型转换器:

public class ThicknessConverter : TypeConverter
{
    public ThicknessConverter()
    {
    }

    public override Boolean CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(String) || destinationType == typeof(InstanceDescriptor);
    }
    public override Object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, Object value, Type destinationType)
    {
        Thickness thickness = (Thickness)value;
        if (destinationType == typeof(String))
        {
            if (thickness.IsUniform)
                return thickness.Right.ToString();
            else return thickness.Left + "," + thickness.Top + "," + thickness.Right + "," + thickness.Bottom;
        }
        else if (destinationType == typeof(InstanceDescriptor))
        {
            if (thickness.IsUniform)
                return new InstanceDescriptor(typeof(Thickness).GetConstructor(new Type[] { typeof(Double) }), new Object[] { thickness.UniformLength });
            else
            {
                ConstructorInfo constructor = typeof(Thickness).GetConstructor(new Type[] { typeof(Double), typeof(Double), typeof(Double), typeof(Double) });
                return new InstanceDescriptor(constructor, new Object[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
            }
        }
        else return null;
    }
    public override Boolean CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(String);
    }
    public override Object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, Object value)
    {
        if (value is String)
        {
            String stringValue = (String)value;
            if (stringValue.Contains(","))
            {
                String[] stringValues = stringValue.Split(',');
                Double[] values = new Double[stringValues.Length];
                if (values.Length == 4)
                {
                    try
                    {
                        for (Int32 i = 0; i < 4; i++)
                            values[i] = Double.Parse(stringValues[i]);
                    }
                    catch (Exception)
                    {
                        return new Thickness();
                    }
                    return new Thickness(values[0], values[1], values[2], values[3]);
                }
                else return new Thickness();
            }
            else
            {
                try
                {
                    return new Thickness(Double.Parse(stringValue));
                }
                catch (Exception)
                {
                    return new Thickness();
                }
            }
        }
        else return base.ConvertFrom(context, culture, value);
    }
    public override Boolean GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }
    public override Object CreateInstance(ITypeDescriptorContext context, System.Collections.IDictionary propertyValues)
    {
        return new Thickness((Double)propertyValues["Left"], (Double)propertyValues["Top"], (Double)propertyValues["Right"], (Double)propertyValues["Bottom"]);
    }

    public override Boolean GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, Object value, Attribute[] attributes)
    {
        PropertyDescriptorCollection collection = TypeDescriptor.GetProperties(typeof(Thickness));
        collection = collection.Sort(new String[] { "Left", "Top", "Right", "Bottom" });
        collection.RemoveAt(4);
        collection.RemoveAt(4);
        return collection;
    }
}

我唯一能想到的是转换器是否必须与使用它的设计器代码位于单独的程序集中?

4

2 回答 2

5

所以,我希望我的调查能够成功结束。

结果:
这很奇怪。VS2008似乎有一些错误。
要使您的代码按预期工作:
1. 重命名ThicknessConverter为其他名称(例如:)Thickness1Converter
2. 按 构建解决方案Shift+F6

现在您应该能够Thickness在设计器 UI 中编辑该属性。相应的代码将出现在*.Designer.cs文件中。

之后,在某些情况下,可以将其重命名为 ,ThicknessConverter而不会出现错误。但是我找不到规则,对不起。

如果有什么不够清楚,请随时问我。

祝你好运。

于 2013-11-17T01:51:13.123 回答
3

这对我来说很好。以下是我遵循的步骤:

  1. 启动VS2010。
  2. 创建一个新的 WinForms 项目(.NET Framework 4 客户端配置文件)。
  3. 复制粘贴您的 Thickness 和 ThicknessConverter 类。
  4. 创建一个新的用户控件 UserControl1。
  5. 向用户控件添加一个属性:public Thickness Thickness { get; set; }
  6. 构建项目。
  7. 打开 Form1 设计器。
  8. 在 Form1 上放置一个 UserControl1。
  9. 选择用户控件 1。
  10. 编辑厚度属性。
  11. 节省。
  12. 验证 Form1.Designer.cs 中的厚度是否正确。

如果这对您不起作用,您要么在项目中做其他事情,要么我们的设置有所不同。您能否提供详细信息(例如 .NET 版本)?

于 2013-11-13T22:30:05.273 回答