1、新建一个自定义Editor,继承自.NET自带的Editor,override某些方法,再附加到属性中:
public class MyCollectionEditor : CollectionEditor { public MyCollectionEditor(Type type) : base(type) { } protected override void ShowHelp() { MessageBox.Show("别点了,点了也没用。"); } } [Editor(typeof(MyCollectionEditor), typeof(UITypeEditor))] public List<B> Bs2 { get; set; }
上图就在列表编辑框中重定义了点击“Help”时的操作。一般都是这么用的。
2、常见Editor
1)ArrayEditor,继承自CollectionEditor
2)BinaryEditor
3)CollectionEditor
4)DateTimeEditor
5)MultilineStringEditor
6)BitmapEditor,继承自ImageEditor
7)ColorEditor
8)ContentAlignmentEditor
9)CursorEditor
10)FontEditor
11)FontNameEditor
12)IconEditor
13)ImageEditor
14)MetafileEditor
15)UITypeEditor,所有这些的基类,他们能继承自它,我们怎么不行?
16)QueuePathEditor
17)DataControlReferenceCollectionEditor,继承自CollectionEditor
18)AppSettingsExpressionEditor,继承自ExpressionEditor
19)CollectionEditorBase,继承自CollectionEditor
20)ConnectionStringEditor
21)ConnectionStringsExpressionEditor,继承自ExpressionEditor
22)DataBindingCollectionEditor
23)ExpressionEditor
24)ExpressionCollectionEditor
25)ImageUrlEditor,继承自UrlEditor
26)MailFileEditor,继承自UrlEditor
27)MdbDataFileEditor,继承自UrlEditor
28)ResourceExpressionEditor,继承自ExpressionEditor
29)RouteUrlEditor,继承自ExpressionEditor
30)RouteValueExpressionEditor,继承自ExpressionEditor
31)ServiceReferenceCollectionEditor,继承自CollectionEditorBase
32)UpdatePanelTriggerCollectionEditor,继承自CollectionEditorBase
33)UrlEditor
34)UserControlFileEditor,继承自UrlEditor
35)AnchorEditor
36)BorderSidesEditor
37)DockEditor
38)FileNameEditor
39)FolderNameEditor
40)FormatStringEditor
41)ImageListImageEditor
42)ShortcutKeysEditor
43)BindingUIEditor
44)TypeBrowserEditor
还有部分Web命名空间下的没有记录,寻找方法,在对象浏览器中,搜索Editor,找出以Editor结尾,并继承自UITypeEditor的类即可。
3、可展开项的示例
[TypeConverter(typeof(ExpandableObjectConverter))] public class B { public int Name1 { get; set; } public int Name2 { get; set; } public override string ToString() { return Name1 + "-" + Name2; } } public class A { public A() { if (Bs == null) { Bs = new B(); } } public B Bs { get; set; } }
4、下拉框的示例
public class XXXConverter : StringConverter { public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { return new StandardValuesCollection(StringArray); } public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } public static string[] StringArray = new[] { "AAA", "BBB" }; }
[TypeConverter(typeof(XXXConverter))] public string Name2 { get; set; }
5、有效性验证示例
public class OneTo32Converter : Int32Converter { public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var result = (int)base.ConvertFrom(context, culture, value); if (result < 1 || result > 32) { throw new Exception("输入值要在1至32之间。"); } return result; } }
[TypeConverter(typeof(OneTo32Converter))] public int Name1 { get; set; }
6、数组自定义显示及去除展开对话框示例
public class XXXArrayConverter : ArrayConverter { public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { return "sssss"; } }
[TypeConverter(typeof(XXXArrayConverter)), Editor(typeof(UITypeEditor), typeof(UITypeEditor))] public B[] Bs { get; set; }
7、Converter及Editor总结
如果附在uint类型的属性上,则:
Converter是用于该属性的类型uint与用于显示的类型string之间的转换;
ConvertFrom是string转换成uint;
ConvertTo是uint转换成string;
如果使用DateTimeEditor,则:
该Editor是用于uint与DateTime之间的转换;
而DateTimeEditor只会处理DateTime与DateTime之间的转换,所以要在EditValue方法中完成uint与DateTime的转换。
public class MyDateTimeEditor : DateTimeEditor { public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { var result = (DateTime) base.EditValue(context, provider, new DateTime(1970, 1, 1).AddSeconds((uint) value)); return (uint) ((result - new DateTime(1970, 1, 1)).TotalSeconds); } }
[TypeConverter(typeof(UInt32Converter)), Editor(typeof(MyDateTimeEditor), typeof(UITypeEditor))] public uint C { get; set; }
Converter用于处理输入值时的行为,常用于有效性验证、格式转换等,而Editor用于处理下拉或打开新窗口时的行为。它们可以在同一个属性上共存。
8、自定义窗体示例
public class MyUITypeEditor : UITypeEditor { public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { var picker = new Form1((uint) value); if (picker.ShowDialog() == DialogResult.OK) { return picker.Seconds; } return value; } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } }
9、可编辑复合对象
public class A { public A() { if (EndPoint == null) { EndPoint = new PGIPEndPoint { IPAddress = "255.255.255.255", Port = 65535 }; } } [TypeConverter(typeof(IPEndPointConverter))] public PGIPEndPoint EndPoint { get; set; } }
public class IPEndPointConverter : ExpandableObjectConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return true; } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return true; } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var result = ((string)value).Split(':'); var ip = IPAddress.Parse(result[0]); var port = Convert.ToInt32(result[1]); if (port < 0 || port > 65535) { throw new Exception(string.Format("{0}要在0至65535之间。", port)); } return new PGIPEndPoint { IPAddress = ip.ToString(), Port = port }; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { var result = (PGIPEndPoint)value; return string.Format("{0}:{1}", result.IPAddress, result.Port); } } public class PGIPEndPoint { [TypeConverter(typeof(IPConverter))] public string IPAddress { get; set; } [TypeConverter(typeof(ZeroTo65535Converter))] public int Port { get; set; } } public class ZeroTo65535Converter : Int32Converter { public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var result = Convert.ToInt32(value); if (result < 0 || result > 65535) { throw new Exception(string.Format("{0}要在0至65535之间。", result)); } return result; } } public class IPConverter : StringConverter { public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { return (IPAddress.Parse((string)value)).ToString(); } }
10、属性的显示顺序
把PropertyGrid控件的PropertySort设置为NoSort可使属性以其被截取時的顺序显示。
11、去除工具栏
把ToolBarVisible设置为False。