当你在制作组件时遇到难以构造,解释的或者取值过多,比较复杂的或者难以用一个字符串来表示的视觉效果属性时,你需要实现UI类型编辑器。常见属性ForeColor属性就是一个很好的例子,这种可视化编辑风格使得属性值的选择更方便,更美观!
实现一个定制的UI编辑器:
当你在制作组件时遇到难以构造,解释的或者取值过多,比较复杂的或者难以用一个字符串来表示的视觉效果属性时,你需要实现UI类型编辑器。常见属性ForeColor属性就是一个很好的例子,这种可视化编辑风格使得属性值的选择更方便,更美观!
实现一个定制的UI编辑器:
1.从UITypeEditor基类派生一个新类。
2.对继承自基类的GetEditStyle和EditValue方法进行覆盖。
具体实现:
1.访问属性浏览器的UI显示服务IWindowsFormsEditorService。
2.创建该编辑器UI实现的一个实例。
3.把当前属性的值传递给你在第2步创建的UI编辑器控件。
4.请求属性浏览器显示这个UI编辑器控件。
5.选择一个新的属性值并关闭这个UI编辑器控件。
6.从这个编辑器返回,返回值就是你在第5步选择的新属性值。
还是以ClockControl为例(参考前文:《.Net窗体设计阶段的功能集成问答》和《类型转换器的定制》,附源代码),为它的Face属性提供一个下拉式编辑器:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
FaceEditor
1![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class FaceEditor : System.Drawing.Design.UITypeEditor
{
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
3![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( context != null )
{
4
return UITypeEditorEditStyle.DropDown;
5
}
6
return base.GetEditStyle(context);
7
}
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
9![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( (context != null) && (provider != null) )
{
11
// Access the property browser抯 UI display service, IWindowsFormsEditorService
12
IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
13![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( editorService != null )
{
15
// Create an instance of the UI editor control, passing a reference to the editor service
16
FaceEditorControl dropDownEditor = new FaceEditorControl(editorService);
17![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
// Pass the UI editor control the current property value
19
dropDownEditor.Face = (ClockFace)value;
20![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
// Display the UI editor control
22
editorService.DropDownControl(dropDownEditor);
23![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
// Return the new property value from the UI editor control
25
return dropDownEditor.Face;
26
}
27
}
28
return base.EditValue(context, provider, value);
29
}
30
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
FaceEditorControl
1![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
2
/// Summary description for FaceEditorControl.
3
/// </summary>
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
internal class FaceEditorControl : System.Windows.Forms.UserControl
{
5
private System.Windows.Forms.PictureBox picDigital;
6
private System.Windows.Forms.PictureBox picAnalog;
7
private System.Windows.Forms.PictureBox picBoth;
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// Required designer variable.
10
/// </summary>
11
private System.ComponentModel.Container components = null;
12![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
public FaceEditorControl()
14![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
15
// This call is required by the Windows.Forms Form Designer.
16
InitializeComponent();
17![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
// TODO: Add any initialization after the InitForm call
19![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
}
21![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
23
/// Clean up any resources being used.
24
/// </summary>
25
protected override void Dispose( bool disposing )
26![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
27
if( disposing )
28![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
if(components != null)
30![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
31
components.Dispose();
32
}
33
}
34
base.Dispose( disposing );
35
}
36![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Component Designer generated code#region Component Designer generated code
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
39
/// Required method for Designer support - do not modify
40
/// the contents of this method with the code editor.
41
/// </summary>
42
private void InitializeComponent()
43![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
44
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(FaceEditorControl));
45
this.picDigital = new System.Windows.Forms.PictureBox();
46
this.picAnalog = new System.Windows.Forms.PictureBox();
47
this.picBoth = new System.Windows.Forms.PictureBox();
48
this.SuspendLayout();
49
//
50
// picDigital
51
//
52
this.picDigital.BackColor = System.Drawing.SystemColors.Highlight;
53
this.picDigital.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
54
this.picDigital.Image = ((System.Drawing.Bitmap)(resources.GetObject("picDigital.Image")));
55
this.picDigital.Location = new System.Drawing.Point(152, 8);
56
this.picDigital.Name = "picDigital";
57
this.picDigital.Size = new System.Drawing.Size(65, 65);
58
this.picDigital.TabIndex = 8;
59
this.picDigital.TabStop = false;
60
this.picDigital.Click += new System.EventHandler(this.picDigital_Click);
61
//
62
// picAnalog
63
//
64
this.picAnalog.BackColor = System.Drawing.SystemColors.Highlight;
65
this.picAnalog.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
66
this.picAnalog.Image = ((System.Drawing.Bitmap)(resources.GetObject("picAnalog.Image")));
67
this.picAnalog.Location = new System.Drawing.Point(80, 8);
68
this.picAnalog.Name = "picAnalog";
69
this.picAnalog.Size = new System.Drawing.Size(65, 65);
70
this.picAnalog.TabIndex = 7;
71
this.picAnalog.TabStop = false;
72
this.picAnalog.Click += new System.EventHandler(this.picAnalog_Click);
73
//
74
// picBoth
75
//
76
this.picBoth.BackColor = System.Drawing.SystemColors.Highlight;
77
this.picBoth.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
78
this.picBoth.Image = ((System.Drawing.Bitmap)(resources.GetObject("picBoth.Image")));
79
this.picBoth.Location = new System.Drawing.Point(8, 8);
80
this.picBoth.Name = "picBoth";
81
this.picBoth.Size = new System.Drawing.Size(65, 65);
82
this.picBoth.TabIndex = 6;
83
this.picBoth.TabStop = false;
84
this.picBoth.Click += new System.EventHandler(this.picBoth_Click);
85
//
86
// FaceEditorControl
87
//
88
this.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(236)), ((System.Byte)(233)), ((System.Byte)(216)));
89![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
this.Controls.AddRange(new System.Windows.Forms.Control[]
{
90
this.picDigital,
91
this.picAnalog,
92
this.picBoth});
93
this.Name = "FaceEditorControl";
94
this.Size = new System.Drawing.Size(223, 80);
95
this.ResumeLayout(false);
96![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
97
}
98
#endregion
99![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
100
private ClockFace face = ClockFace.Both;
101
private IWindowsFormsEditorService editorService = null;
102![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public FaceEditorControl(IWindowsFormsEditorService editorService)
{
104
InitializeComponent();
105
this.editorService = editorService;
106
}
107![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
108![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public ClockFace Face
{
109![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return face; }
110![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{
111
face = value;
112![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( face == ClockFace.Both )
{
113
this.picBoth.BackColor = Color.Red;
114
return;
115
}
116![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( face == ClockFace.Analog )
{
117
this.picAnalog.BackColor = Color.Red;
118
return;
119
}
120![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if( face == ClockFace.Digital )
{
121
this.picDigital.BackColor = Color.Red;
122
return;
123
}
124
}
125
}
126![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
127![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void picBoth_Click(object sender, System.EventArgs e)
{
128
face = ClockFace.Both;
129![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
130
// Close the UI editor upon value selection
131
editorService.CloseDropDown();
132
}
133![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
134![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void picAnalog_Click(object sender, System.EventArgs e)
{
135
face = ClockFace.Analog;
136![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
137
// Close the UI editor upon value selection
138
editorService.CloseDropDown();
139
}
140![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
141![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void picDigital_Click(object sender, System.EventArgs e)
{
142
face = ClockFace.Digital;
143![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
144
// Close the UI editor upon value selection
145
editorService.CloseDropDown();
146
}
147![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
148![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected override void OnPaint(PaintEventArgs pe)
{
149![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
150
// Get currently selected control
151
PictureBox selected;
152
if( face == ClockFace.Both ) selected = this.picBoth;
153
else if( face == ClockFace.Analog ) selected = this.picAnalog;
154
else selected = this.picDigital;
155![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
156
// Paint the border
157
Graphics g = pe.Graphics;
158![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
using( Pen pen = new Pen(Color.Gray, 1) )
{
159
pen.DashStyle = DashStyle.Dash;
160
g.DrawLine( pen, new Point(selected.Left - 2, selected.Top - 2), new Point(selected.Left + selected.Width + 1, selected.Top - 2));
161
g.DrawLine( pen, new Point(selected.Left + selected.Width + 1, selected.Top - 2), new Point(selected.Left + selected.Width + 1, selected.Top + selected.Height + 1));
162
g.DrawLine( pen, new Point(selected.Left + selected.Width + 1, selected.Top + selected.Height + 1), new Point(selected.Left - 2, selected.Top + selected.Height + 1));
163
g.DrawLine( pen, new Point(selected.Left - 2, selected.Top + selected.Height + 1), new Point(selected.Left - 2, selected.Top - 2));
164
}
165
base.OnPaint(pe);
166
}
167
}