上一篇博文探讨了如何自定义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 效果