为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
而不会出现错误。 但对不起,我无法发现规则。
如果事情不够清楚,请不要犹豫,问我。
祝好运。
这对我来说很好。 以下是我遵循的步骤:
- 启动VS2010。
- 创建一个新的WinForms项目(.NET Framework 4 Client Profile)。
- 复制粘贴Thickness和ThicknessConverter类。
- 创建一个新的用户控件UserControl1。
- 向用户控件添加属性:
public Thickness Thickness { get; set; }
public Thickness Thickness { get; set; }
- 建立项目。
- 打开Form1设计器。
- 在Form1上放置UserControl1。
- 选择UserControl1。
- 编辑厚度属性。
- 保存。
- 在Form1.Designer.cs中validation厚度是否正确。
如果这不适合您,您要么在项目中做其他事情,要么我们的设置有所不同。 您能提供详细信息(例如.NET版本)吗?