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。