如何为自定义控件添加 Point 属性的设计师支持?

3

我有一个自定义控件,它有一个名为 Offset 的属性,类型为 PointF。

我想能够从表单设计器编辑该属性(它当前被禁用了)。

我读到必须添加 EditorAttribute,它指向从 System.Drawing.Design.UITypeEditor 派生的类。

看起来有很多内置类型已经派生自 UITypeEditor,比如:

System.ComponentModel.Design.BinaryEditor
System.ComponentModel.Design.CollectionEditor
System.ComponentModel.Design.DateTimeEditor
System.ComponentModel.Design.MultilineStringEditor
System.ComponentModel.Design.ObjectSelectorEditor
System.Drawing.Design.ColorEditor
System.Drawing.Design.ContentAlignmentEditor
System.Drawing.Design.CursorEditor
System.Drawing.Design.FontEditor
System.Drawing.Design.FontNameEditor
System.Drawing.Design.IconEditor

我找不到编辑PointF或Point类型的方法。因为.NET在设计时一直暴露Point/PointF类型,所以这个功能似乎应该已经存在。

我希望不必重复造轮子-如果已经存在内置的UITypeEditor类型,则想使用它。

谢谢。

1个回答

3

您可以使用以下代码将一个类型为Point的自定义控件的属性添加到控件的属性网格中以进行编辑:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
 EditorBrowsable(EditorBrowsableState.Advanced),
 TypeConverter(typeof(PointConverter))]
public Point MyPointProperty { get; set; }

如果您尝试使用相同的方法来处理SizeF,您会发现.NET中没有内置的TypeConverter来支持PointF。不过,您可以创建自己的TypeConverter,我在这里找到了一个(并复制并粘贴了下面大部分的代码)。
有了PointF TypeConverter,您可以编写一个PointF类型的属性,在属性窗口中对其进行编辑。
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
 EditorBrowsable(EditorBrowsableState.Advanced),
 TypeConverter(typeof(PointFConverter))]
public PointF MyPointFProperty { get; set; }

以下是在上述文章中找到的PointF类型转换器代码:
/// <summary>
/// PointFConverter
/// </summary>
public class PointFConverter : ExpandableObjectConverter
{
    /// <summary>
    /// Creates a new instance of PointFConverter
    /// </summary>
    public PointFConverter() {
    }

    /// <summary>
    /// Boolean, true if the source type is a string
    /// </summary>
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
        if (sourceType == typeof(string)) return true;
        return base.CanConvertFrom(context, sourceType);
    }

    /// <summary>
    /// Converts the specified string into a PointF
    /// </summary>
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) {
        if (value is string) {
            try {
                string s = (string)value;
                string[] converterParts = s.Split(',');
                float x = 0;
                float y = 0;
                if (converterParts.Length > 1) {
                    x = float.Parse(converterParts[0].Trim());
                    y = float.Parse(converterParts[1].Trim());
                } else if (converterParts.Length == 1) {
                    x = float.Parse(converterParts[0].Trim());
                    y = 0;
                } else {
                    x = 0F;
                    y = 0F;
                }
                return new PointF(x, y);
            } catch {
                throw new ArgumentException("Cannot convert [" + value.ToString() + "] to pointF");
            }
        }
        return base.ConvertFrom(context, culture, value);
    }

    /// <summary>
    /// Converts the PointF into a string
    /// </summary>
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) {
        if (destinationType == typeof(string)) {
            if (value.GetType() == typeof(PointF)) {
                PointF pt = (PointF)value;
                return string.Format("{0}, {1}", pt.X, pt.Y);
            }
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

我按照你在这里说的做了,但是在设计器中(VS 2012)PointF属性仍然是只读的。 - Pedro77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接