上一篇博文探讨了如何自定义DataGridViewColumn实现一个TreeViewColumn来在DataGridView控件中显示TreeView控件,其实我们还可以继续发挥想象,自定义其他的列类型,下面介绍一个脚本编辑器列类型,我这里取名ScriptTextEditorColumn,当用户单击DataGridView的ScriptTextEditorColumn时,单元格右边会出现一个按钮,单击按钮会弹出一个脚本编辑器窗体,用户可以在窗体中进行代码维护,然后回写到单元格中。
用人会问,这个控件有啥实际作用,其实结合动态编译的技术,在datagridview中进行取值公式的模板设定,也就是在对应的单元格中设置C#脚本,然后动态执行后呈现结果到一个datagridview单元格中,这样就实现了动态配置datagridview后台计算逻辑的目的,当然实现这样的功能还需要大量的工作,但是主要的思路就是这样。
1 ScriptTextEditorColumn
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows.Forms;
6
7 namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
8 {
9 public class ScriptTextEditorColumn : DataGridViewColumn
10 {
11 public ScriptTextEditorColumn()
12 : base(new ScriptTextEditorCell())
13 {
14 }
15
16 public override DataGridViewCell CellTemplate
17 {
18 get
19 {
20 return base.CellTemplate;
21 }
22 set
23 {
24 // Ensure that the cell used for the template is a ScriptTextEditorCell.
25 if (value != null &&
26 !value.GetType().IsAssignableFrom(typeof(ScriptTextEditorCell)))
27 {
28 throw new InvalidCastException("Must be a ScriptTextEditorCell");
29 }
30 base.CellTemplate = value;
31 }
32 }
33 }
34
35 //----------------------------------------------------------------------
36 public class ScriptTextEditorCell : DataGridViewTextBoxCell
37 {
38
39 public ScriptTextEditorCell()
40 : base()
41 {
42
43 }
44
45 public override void InitializeEditingControl(int rowIndex, object
46 initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
47 {
48 // Set the value of the editing control to the current cell value.
49 base.InitializeEditingControl(rowIndex, initialFormattedValue,
50 dataGridViewCellStyle);
51 ScriptTextEditingControl ctl =
52 DataGridView.EditingControl as ScriptTextEditingControl;
53 // Use the default row value when Value property is null.
54 if (this.Value == null)
55 {
56 ctl.textBox1.Text = (String)this.DefaultNewRowValue;
57 }
58 else
59 {
60 ctl.textBox1.Text = (String)this.Value;
61 }
62 }
63
64 public override Type EditType
65 {
66 get
67 {
68 // Return the type of the editing control that CalendarCell uses.
69 return typeof(ScriptTextEditingControl);
70 }
71 }
72
73 public override Type ValueType
74 {
75 get
76 {
77 // Return the type of the value that CalendarCell contains.
78
79 return typeof(String);
80 }
81 }
82
83 public override object DefaultNewRowValue
84 {
85 get
86 {
87 // Use the current date and time as the default value.
88 string code = @"
89 #region
90 //jackwangcumt
91 #endregion
92 using System;
93 using System.Collections.Generic;
94 using System.ComponentModel;
95 using System.Drawing;
96 using System.Data;
97 using System.Linq;
98 using System.Text;
99 using System.Windows.Forms;
100 namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
101 {
102 public partial class SourceTextBox : UserControl
103 {
104 public SourceTextBox()
105 {
106 InitializeComponent();
107 this.textBox1.Location = this.Location;
108 this.textBox1.Width = this.Width;
109 this.textBox1.Height = this.Height;
110 }
111 protected void OnValueChanged(string text)
112 {
113 this.textBox1.Text = text;
114 }
115
116 private void btnSource_Click(object sender, EventArgs e)
117 {
118 ScriptEditor frm = new ScriptEditor(this.textBox1.Text);
119 frm.ShowDialog();
120 this.textBox1.Text = frm.fastColoredTextBox1.Text;
121 }
122 }
123 }
124 ";
125 return code;
126 }
127 }
128 }
129 //-----------------------------------------------------------------
130
131 class ScriptTextEditingControl : SourceTextBox, IDataGridViewEditingControl
132 {
133 DataGridView dataGridView;
134 private bool valueChanged = false;
135 int rowIndex;
136
137 public ScriptTextEditingControl()
138 {
139 //文本变更更新到cell
140 this.textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
141 }
142
143 void textBox1_TextChanged(object sender, EventArgs e)
144 {
145 // Notify the DataGridView that the contents of the cell
146 // have changed.
147 valueChanged = true;
148 this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
149 //调用SourceTextBox的OnValueChanged(string Text)
150 base.OnValueChanged(this.textBox1.Text);
151 }
152
153 // Implements the IDataGridViewEditingControl.EditingControlFormattedValue
154 // property.
155 public object EditingControlFormattedValue
156 {
157 get
158 {
159 return this.textBox1.Text;
160 }
161 set
162 {
163 if (value is String)
164 {
165 try
166 {
167 // This will throw an exception of the string is
168 // null, empty, or not in the format of a date.
169 this.textBox1.Text=((String)value);
170 }
171 catch
172 {
173 // In the case of an exception, just use the
174 // default value so we're not left with a null
175 // value.
176 this.textBox1.Text = "jackwangcumt>>error";
177 }
178 }
179 }
180 }
181
182 // Implements the
183 // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
184 public object GetEditingControlFormattedValue(
185 DataGridViewDataErrorContexts context)
186 {
187 return EditingControlFormattedValue;
188 }
189
190 // Implements the
191 // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
192 public void ApplyCellStyleToEditingControl(
193 DataGridViewCellStyle dataGridViewCellStyle)
194 {
195 this.Font = dataGridViewCellStyle.Font;
196 //this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
197 //this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
198 }
199
200 // Implements the IDataGridViewEditingControl.EditingControlRowIndex
201 // property.
202 public int EditingControlRowIndex
203 {
204 get
205 {
206 return rowIndex;
207 }
208 set
209 {
210 rowIndex = value;
211 }
212 }
213
214 // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey
215 // method.
216 public bool EditingControlWantsInputKey(
217 Keys key, bool dataGridViewWantsInputKey)
218 {
219 // Let the DateTimePicker handle the keys listed.
220 switch (key & Keys.KeyCode)
221 {
222 case Keys.Left:
223 case Keys.Up:
224 case Keys.Down:
225 case Keys.Right:
226 case Keys.Home:
227 case Keys.End:
228 case Keys.PageDown:
229 case Keys.PageUp:
230 return true;
231 default:
232 return !dataGridViewWantsInputKey;
233 }
234 }
235
236 // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit
237 // method.
238 public void PrepareEditingControlForEdit(bool selectAll)
239 {
240 // No preparation needs to be done.
241 }
242
243 // Implements the IDataGridViewEditingControl
244 // .RepositionEditingControlOnValueChange property.
245 public bool RepositionEditingControlOnValueChange
246 {
247 get
248 {
249 return false;
250 }
251 }
252
253 // Implements the IDataGridViewEditingControl
254 // .EditingControlDataGridView property.
255 public DataGridView EditingControlDataGridView
256 {
257 get
258 {
259 return dataGridView;
260 }
261 set
262 {
263 dataGridView = value;
264 }
265 }
266
267 // Implements the IDataGridViewEditingControl
268 // .EditingControlValueChanged property.
269 public bool EditingControlValueChanged
270 {
271 get
272 {
273 return valueChanged;
274 }
275 set
276 {
277 valueChanged = value;
278 }
279 }
280
281 // Implements the IDataGridViewEditingControl
282 // .EditingPanelCursor property.
283 public Cursor EditingPanelCursor
284 {
285 get
286 {
287 return base.Cursor;
288 }
289 }
290
291 protected override void OnTextChanged(EventArgs e)
292 {
293 // Notify the DataGridView that the contents of the cell
294 // have changed.
295 valueChanged = true;
296 this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
297 base.OnTextChanged(e);
298
299 }
300
301 }
302
303
304
305 }
2 SourceTextBox
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9
10 namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
11 {
12 public partial class SourceTextBox : UserControl
13 {
14 public SourceTextBox()
15 {
16 InitializeComponent();
17 this.textBox1.Location = this.Location;
18 this.textBox1.Width = this.Width;
19 this.textBox1.Height = this.Height;
20 }
21 protected void OnValueChanged(string text)
22 {
23 this.textBox1.Text = text;
24 }
25
26 private void btnSource_Click(object sender, EventArgs e)
27 {
28 ScriptEditor frm = new ScriptEditor(this.textBox1.Text);
29 frm.ShowDialog();
30 this.textBox1.Text = frm.fastColoredTextBox1.Text;
31 }
32 }
33 }
1 namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
2 {
3 partial class SourceTextBox
4 {
5 /// <summary>
6 /// 必需的设计器变量。
7 /// </summary>
8 private System.ComponentModel.IContainer components = null;
9
10 /// <summary>
11 /// 清理所有正在使用的资源。
12 /// </summary>
13 /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14 protected override void Dispose(bool disposing)
15 {
16 if (disposing && (components != null))
17 {
18 components.Dispose();
19 }
20 base.Dispose(disposing);
21 }
22
23 #region 组件设计器生成的代码
24
25 /// <summary>
26 /// 设计器支持所需的方法 - 不要
27 /// 使用代码编辑器修改此方法的内容。
28 /// </summary>
29 private void InitializeComponent()
30 {
31 this.textBox1 = new System.Windows.Forms.TextBox();
32 this.btnSource = new System.Windows.Forms.Button();
33 this.SuspendLayout();
34 //
35 // textBox1
36 //
37 this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
38 this.textBox1.Location = new System.Drawing.Point(3, 3);
39 this.textBox1.Margin = new System.Windows.Forms.Padding(4);
40 this.textBox1.Multiline = true;
41 this.textBox1.Name = "textBox1";
42 this.textBox1.Size = new System.Drawing.Size(175, 21);
43 this.textBox1.TabIndex = 1;
44 //
45 // btnSource
46 //
47 this.btnSource.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
48 | System.Windows.Forms.AnchorStyles.Right)));
49 this.btnSource.BackColor = System.Drawing.Color.Transparent;
50 this.btnSource.BackgroundImage = global::Host_Controls_in_Windows_Forms_DataGridView_Cells.Resource.setting;
51 this.btnSource.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
52 this.btnSource.FlatAppearance.BorderColor = System.Drawing.Color.White;
53 this.btnSource.FlatAppearance.BorderSize = 0;
54 this.btnSource.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
55 this.btnSource.Font = new System.Drawing.Font("新宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
56 this.btnSource.Location = new System.Drawing.Point(159, -1);
57 this.btnSource.Margin = new System.Windows.Forms.Padding(0);
58 this.btnSource.Name = "btnSource";
59 this.btnSource.Size = new System.Drawing.Size(19, 25);
60 this.btnSource.TabIndex = 0;
61 this.btnSource.UseVisualStyleBackColor = false;
62 this.btnSource.Click += new System.EventHandler(this.btnSource_Click);
63 //
64 // SourceTextBox
65 //
66 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
67 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
68 this.Controls.Add(this.btnSource);
69 this.Controls.Add(this.textBox1);
70 this.Margin = new System.Windows.Forms.Padding(0);
71 this.Name = "SourceTextBox";
72 this.Size = new System.Drawing.Size(178, 26);
73 this.ResumeLayout(false);
74 this.PerformLayout();
75
76 }
77
78 #endregion
79
80 public System.Windows.Forms.Button btnSource;
81 public System.Windows.Forms.TextBox textBox1;
82 }
83 }
3 效果