为Windows窗体实现TypeConverter

我想为自定义类型厚度实现TypeConverter。 我查看了像SizeConverter这样的微软发布的类型转发器 。

当我在我的Thickness属性上键入字符串或更改其中一个属性时,设计器使用它,它只是不将更改保存到’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; } } 

我唯一能想到的是转换器是否必须与使用它的设计器代码分开组装?

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

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

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

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

如果事情不够清楚,请不要犹豫,问我。

祝好运。

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

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

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