C#如何自定义DataGridViewColumn来显示TreeView

  我们可以自定义DataGridView的DataGridViewColumn来实现自定义的列,下面介绍一下如何通过扩展DataGridViewColumn来实现一个TreeViewColumn

1 TreeViewColumn类

 TreeViewColumn继承自DataGridViewColumn,为了动态给TreeViewColumn传入一个TreeView,这里暴露出一个公共属性_root,可以绑定一个初始化的TreeView. 另外需要重写DataGridCell类型的CellTemplate,这里返还一个TreeViewCell(需要自定义)

 1     /// <summary>
 2     /// Host TreeView In DataGridView Cell
 3     /// </summary>
 4    public class TreeViewColumn : DataGridViewColumn
 5     {
 6         public TreeViewColumn()
 7             : base(new TreeViewCell())
 8         {
 9         }
10         [Description("Set TreeView Root in DataGridView Cell"), Category("TreeView")]
11         public TreeView _root
12         {
13             get{return Roots.tree;}
14             set{Roots.tree=value;}
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 TreeViewCell.
25                 if (value != null &&
26                     !value.GetType().IsAssignableFrom(typeof(TreeViewCell)))
27                 {
28                     throw new InvalidCastException("Must be a TreeViewCell");
29                 }
30                 base.CellTemplate = value;
31             }
32         }
33     }

2 TreeViewCell类

    上面TreeViewColumn重写了CellTemplate,返回的就是自定义的TreeViewCell,这里就是具体实现其逻辑。一般来说选择树控件的节点后,返回的是一个文本信息,是文本类型,可以继承DataGridViewTextBoxCell,并重写InitializeEditingControl来进行自定义的DataGridView.EditingControl (编辑控件)。

 1   public class TreeViewCell : DataGridViewTextBoxCell
 2     {
 3 
 4         public TreeViewCell()
 5             : base()
 6         {
 7         
 8             //初始设置
 9         }
10        
11         public override void InitializeEditingControl(int rowIndex, object
12             initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
13         {
14             // Set the value of the editing control to the current cell value.
15             base.InitializeEditingControl(rowIndex, initialFormattedValue,
16                 dataGridViewCellStyle);
17             TreeViewEditingControl ctl =
18                 DataGridView.EditingControl as TreeViewEditingControl;
19             // Use the default row value when Value property is null.
20             if (this.Value == null)
21             {
22 
23                 ctl.SelectedNode =new TreeNode( this.DefaultNewRowValue.ToString());
24             }
25             else
26             {
27                 ctl.SelectedNode = new TreeNode(this.Value.ToString());
28             }
29         }
30 
31         public override Type EditType
32         {
33             get
34             {
35                 // Return the type of the editing control that CalendarCell uses.
36                 return typeof(TreeViewEditingControl);
37             }
38         }
39 
40         public override Type ValueType
41         {
42             get
43             {
44                 // Return the type of the value that CalendarCell contains.
45                 return typeof(String);
46             }
47         }
48 
49         public override object DefaultNewRowValue
50         {
51             get
52             {
53                 // Use the current date and time as the default value.
54                 return "";
55             }
56         }
57     }

3 TreeViewEditingControl类

  TreeViewEditingControl为编辑控件,当用户编辑TreeViewCell时,显示的为树编辑控件,需要继承TreeView,同时实现IDataGridViewEditingControl接口,实现以下方法:

  1 public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl
  2     {
  3         DataGridView dataGridView;
  4         private bool valueChanged = false;
  5         int rowIndex;
  6         public TreeViewEditingControl()
  7         {
  8             try
  9             {
 10                 //必须加Roots.tree.Nodes[0].Clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆
 11                 this.Nodes.Add(Roots.tree.Nodes[0].Clone() as TreeNode);
 12                 this.SelectedNode = this.Nodes[0];
 13 
 14               
 15             }
 16             catch (Exception ex)
 17             {
 18                 MessageBox.Show(ex.Message);
 19             }
 20            
 21          
 22         }
 23    
 24         // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
 25         // property.
 26         public object EditingControlFormattedValue
 27         {
 28             get
 29             {
 30                 return this.SelectedNode.Text;
 31             }
 32             set
 33             {
 34                 if (value is String)
 35                 {
 36                     try
 37                     {
 38                         // This will throw an exception of the string is 
 39                         // null, empty, or not in the format of a date.
 40                         this.SelectedNode = new TreeNode((String)value);
 41                         
 42                     }
 43                     catch
 44                     {
 45                         // In the case of an exception, just use the 
 46                         // default value so we're not left with a null
 47                         // value.
 48                         this.SelectedNode = new TreeNode("");
 49                     }
 50                 }
 51             }
 52         }
 53 
 54         // Implements the 
 55         // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
 56         public object GetEditingControlFormattedValue(
 57             DataGridViewDataErrorContexts context)
 58         {
 59             return EditingControlFormattedValue;
 60         }
 61 
 62         // Implements the 
 63         // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
 64         public void ApplyCellStyleToEditingControl(
 65             DataGridViewCellStyle dataGridViewCellStyle)
 66         {
 67             this.Font = dataGridViewCellStyle.Font;
 68             this.ForeColor = dataGridViewCellStyle.ForeColor;
 69             this.BackColor = dataGridViewCellStyle.BackColor;
 70         }
 71 
 72         // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
 73         // property.
 74         public int EditingControlRowIndex
 75         {
 76             get
 77             {
 78                 return rowIndex;
 79             }
 80             set
 81             {
 82                 rowIndex = value;
 83             }
 84         }
 85 
 86         // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
 87         // method.
 88         public bool EditingControlWantsInputKey(
 89             Keys key, bool dataGridViewWantsInputKey)
 90         {
 91             // Let the TreeViewPicker handle the keys listed.
 92             switch (key & Keys.KeyCode)
 93             {
 94                 case Keys.Left:
 95                 case Keys.Up:
 96                 case Keys.Down:
 97                 case Keys.Right:
 98                 case Keys.Home:
 99                 case Keys.End:
100                 case Keys.PageDown:
101                 case Keys.PageUp:
102                     return true;
103                 default:
104                     return !dataGridViewWantsInputKey;
105             }
106         }
107 
108         // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
109         // method.
110         public void PrepareEditingControlForEdit(bool selectAll)
111         {
112             // No preparation needs to be done.
113         }
114 
115         // Implements the IDataGridViewEditingControl
116         // .RepositionEditingControlOnValueChange property.
117         public bool RepositionEditingControlOnValueChange
118         {
119             get
120             {
121                 return false;
122             }
123         }

124 
125         // Implements the IDataGridViewEditingControl
126         // .EditingControlDataGridView property.
127         public DataGridView EditingControlDataGridView
128         {
129             get
130             {
131                 return dataGridView;
132             }
133             set
134             {
135                 dataGridView = value;
136             }
137         }
138 
139         // Implements the IDataGridViewEditingControl
140         // .EditingControlValueChanged property.
141         public bool EditingControlValueChanged
142         {
143             get
144             {
145                 return valueChanged;
146             }
147             set
148             {
149                 valueChanged = value;
150             }
151         }
152 
153         // Implements the IDataGridViewEditingControl
154         // .EditingPanelCursor property.
155         public Cursor EditingPanelCursor
156         {
157             get
158             {
159                 return base.Cursor;
160             }
161         }
162 
163         protected override void OnAfterExpand(TreeViewEventArgs e)
164         {
165             base.OnAfterExpand(e);
166             this.dataGridView.Columns[this.dataGridView.CurrentCell.ColumnIndex].Width = this.Width+10;
167             this.dataGridView.Rows[this.dataGridView.CurrentCell.RowIndex].Height = this.Height+20;
168            
169         }
170         protected override void OnAfterSelect(TreeViewEventArgs e)
171         {
172             // Notify the DataGridView that the contents of the cell
173             // have changed.
174             valueChanged = true;
175             this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
176             base.OnAfterSelect(e);
177             
178         }
179        
180     }

  为了在不同类之间传递参数,定义一个全局静态类:

1   /// <summary>
2     /// 静态类的静态属性,用于在不同class间传递参数
3     /// </summary>
4     public static class Roots
5     {
6         //从前台绑定树
7        public static TreeView tree = null;
8     }

完整代码为:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Windows.Forms;
  6 using System.ComponentModel;
  7 namespace Host_Controls_in_Windows_Forms_DataGridView_Cells
  8 {
  9     /// <summary>
 10     /// 静态类的静态属性,用于在不同class间传递参数
 11     /// </summary>
 12     public static class Roots
 13     {
 14         //从前台绑定树
 15        public static TreeView tree = null;
 16     }
 17     /// <summary>
 18     /// Host TreeView In DataGridView Cell
 19     /// </summary>
 20    public class TreeViewColumn : DataGridViewColumn
 21     {
 22         public TreeViewColumn()
 23             : base(new TreeViewCell())
 24         {
 25         }
 26         [Description("Set TreeView Root in DataGridView Cell"), Category("TreeView")]
 27         public TreeView _root
 28         {
 29             get{return Roots.tree;}
 30             set{Roots.tree=value;}
 31         }
 32         public override DataGridViewCell CellTemplate
 33         {
 34             get
 35             {
 36                 return base.CellTemplate;
 37             }
 38             set
 39             {

 40                 // Ensure that the cell used for the template is a TreeViewCell.
 41                 if (value != null &&
 42                     !value.GetType().IsAssignableFrom(typeof(TreeViewCell)))
 43                 {
 44                     throw new InvalidCastException("Must be a TreeViewCell");
 45                 }
 46                 base.CellTemplate = value;
 47             }
 48         }
 49     }
 50 
 51     //----------------------------------------------------------------------
 52     public class TreeViewCell : DataGridViewTextBoxCell
 53     {
 54 
 55         public TreeViewCell()
 56             : base()
 57         {
 58         
 59             //初始设置
 60         }
 61        
 62         public override void InitializeEditingControl(int rowIndex, object
 63             initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
 64         {
 65             // Set the value of the editing control to the current cell value.
 66             base.InitializeEditingControl(rowIndex, initialFormattedValue,
 67                 dataGridViewCellStyle);
 68             TreeViewEditingControl ctl =
 69                 DataGridView.EditingControl as TreeViewEditingControl;
 70             // Use the default row value when Value property is null.
 71             if (this.Value == null)
 72             {
 73 
 74                 ctl.SelectedNode =new TreeNode( this.DefaultNewRowValue.ToString());
 75             }
 76             else
 77             {
 78                 ctl.SelectedNode = new TreeNode(this.Value.ToString());
 79             }
 80         }
 81 
 82         public override Type EditType
 83         {
 84             get
 85             {
 86                 // Return the type of the editing control that CalendarCell uses.
 87                 return typeof(TreeViewEditingControl);
 88             }
 89         }
 90 
 91         public override Type ValueType
 92         {
 93             get
 94             {
 95                 // Return the type of the value that CalendarCell contains.
 96                 return typeof(String);
 97             }
 98         }
 99 
100         public override object DefaultNewRowValue
101         {
102             get
103             {
104                 // Use the current date and time as the default value.
105                 return "";
106             }
107         }
108     }
109     //-----------------------------------------------------------------
110 
111    public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl
112     {
113         DataGridView dataGridView;
114         private bool valueChanged = false;
115         int rowIndex;
116         public TreeViewEditingControl()
117         {
118             try
119             {
120                 //必须加Roots.tree.Nodes[0].Clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆
121                 this.Nodes.Add(Roots.tree.Nodes[0].Clone() as TreeNode);
122                 this.SelectedNode = this.Nodes[0];
123 
124               
125             }
126             catch (Exception ex)
127             {
128                 MessageBox.Show(ex.Message);
129             }
130            
131          
132         }
133    
134         // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
135         // property.
136         public object EditingControlFormattedValue
137         {
138             get
139             {
140                 return this.SelectedNode.Text;
141             }
142             set
143             {
144                 if (value is String)
145                 {
146                     try
147                     {
148                         // This will throw an exception of the string is 
149                         // null, empty, or not in the format of a date.
150                         this.SelectedNode = new TreeNode((String)value);
151                         
152                     }
153                     catch
154                     {
155                         // In the case of an exception, just use the 
156                         // default value so we're not left with a null
157                         // value.
158                         this.SelectedNode = new TreeNode("");
159                     }
160                 }
161             }
162         }
163 
164         // Implements the 
165         // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
166         public object GetEditingControlFormattedValue(
167             DataGridViewDataErrorContexts context)
168         {
169             return EditingControlFormattedValue;
170         }
171 
172         // Implements the 
173         // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
174         public void ApplyCellStyleToEditingControl(
175             DataGridViewCellStyle dataGridViewCellStyle)
176         {
177             this.Font = dataGridViewCellStyle.Font;
178             this.ForeColor = dataGridViewCellStyle.ForeColor;
179             this.BackColor = dataGridViewCellStyle.BackColor;
180         }
181 
182         // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
183         // property.
184         public int EditingControlRowIndex
185         {
186             get
187             {
188                 return rowIndex;
189             }
190             set
191             {
192                 rowIndex = value;
193             }
194         }
195 
196         // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
197         // method.
198         public bool EditingControlWantsInputKey(
199             Keys key, bool dataGridViewWantsInputKey)
200         {
201             // Let the TreeViewPicker handle the keys listed.
202             switch (key & Keys.KeyCode)
203             {
204                 case Keys.Left:
205                 case Keys.Up:
206                 case Keys.Down:
207                 case Keys.Right:
208                 case Keys.Home:
209                 case Keys.End:
210                 case Keys.PageDown:
211                 case Keys.PageUp:
212                     return true;
213                 default:
214                     return !dataGridViewWantsInputKey;
215             }
216         }
217 
218         // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
219         // method.
220         public void PrepareEditingControlForEdit(bool selectAll)
221         {
222             // No preparation needs to be done.
223         }
224 
225         // Implements the IDataGridViewEditingControl
226         // .RepositionEditingControlOnValueChange property.
227         public bool RepositionEditingControlOnValueChange
228         {
229             get
230             {
231                 return false;
232             }
233         }
234 
235         // Implements the IDataGridViewEditingControl
236         // .EditingControlDataGridView property.
237         public DataGridView EditingControlDataGridView
238         {
239             get
240             {
241                 return dataGridView;
242             }
243             set
244             {
245                 dataGridView = value;
246             }
247         }
248 
249         // Implements the IDataGridViewEditingControl
250         // .EditingControlValueChanged property.
251         public bool EditingControlValueChanged
252         {
253             get
254             {
255                 return valueChanged;
256             }
257             set
258             {
259                 valueChanged = value;
260             }
261         }
262 
263         // Implements the IDataGridViewEditingControl
264         // .EditingPanelCursor property.
265         public Cursor EditingPanelCursor
266         {
267             get
268             {
269                 return base.Cursor;
270             }
271         }
272 
273         protected override void OnAfterExpand(TreeViewEventArgs e)
274         {
275             base.OnAfterExpand(e);
276             this.dataGridView.Columns[this.dataGridView.CurrentCell.ColumnIndex].Width = this.Width+10;
277             this.dataGridView.Rows[this.dataGridView.CurrentCell.RowIndex].Height = this.Height+20;
278            
279         }
280         protected override void OnAfterSelect(TreeViewEventArgs e)
281         {
282             // Notify the DataGridView that the contents of the cell
283             // have changed.
284             valueChanged = true;
285             this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
286             base.OnAfterSelect(e);
287             
288         }
289        
290     }
291 
292 
293 
294 }
View Code

  当编辑无误后,可以在添加列的时候看到TreeViewColumn类型。此类型暴露出一个_root属性,可以绑定外部的一个带数据的TreeView。

  运行代码,单击单元格,进入编辑状态,可以看到如下界面:

 

原文地址:https://www.cnblogs.com/isaboy/p/Host_TreeView_in_Windows_Forms_DataGridView_Cells.html