C#自定义DataGridViewColumn显示TreeView
我们可以自定义datagridview的datagridviewcolumn来实现自定义的列,下面介绍一下如何通过扩展datagridviewcolumn来实现一个treeviewcolumn
1.treeviewcolumn类
treeviewcolumn继承自datagridviewcolumn,为了动态给treeviewcolumn传入一个treeview,这里暴露出一个公共属性_root,可以绑定一个初始化的treeview. 另外需要重写datagridcell类型的celltemplate,这里返还一个treeviewcell(需要自定义)
/// <summary> /// host treeview in datagridview cell /// </summary> public class treeviewcolumn : datagridviewcolumn { public treeviewcolumn() : base(new treeviewcell()) { } [description("set treeview root in datagridview cell"), category("treeview")] public treeview _root { get{return roots.tree;} set{roots.tree=value;} } public override datagridviewcell celltemplate { get { return base.celltemplate; } set { // ensure that the cell used for the template is a treeviewcell. if (value != null && !value.gettype().isassignablefrom(typeof(treeviewcell))) { throw new invalidcastexception("must be a treeviewcell"); } base.celltemplate = value; } } }
2.treeviewcell类
上面treeviewcolumn重写了celltemplate,返回的就是自定义的treeviewcell,这里就是具体实现其逻辑。一般来说选择树控件的节点后,返回的是一个文本信息,是文本类型,可以继承datagridviewtextboxcell,并重写initializeeditingcontrol来进行自定义的datagridview.editingcontrol (编辑控件)。
public class treeviewcell : datagridviewtextboxcell { public treeviewcell() : base() { //初始设置 } public override void initializeeditingcontrol(int rowindex, object initialformattedvalue, datagridviewcellstyle datagridviewcellstyle) { // set the value of the editing control to the current cell value. base.initializeeditingcontrol(rowindex, initialformattedvalue, datagridviewcellstyle); treevieweditingcontrol ctl = datagridview.editingcontrol as treevieweditingcontrol; // use the default row value when value property is null. if (this.value == null) { ctl.selectednode =new treenode( this.defaultnewrowvalue.tostring()); } else { ctl.selectednode = new treenode(this.value.tostring()); } } public override type edittype { get { // return the type of the editing control that calendarcell uses. return typeof(treevieweditingcontrol); } } public override type valuetype { get { // return the type of the value that calendarcell contains. return typeof(string); } } public override object defaultnewrowvalue { get { // use the current date and time as the default value. return ""; } } }
3.treevieweditingcontrol类
treevieweditingcontrol为编辑控件,当用户编辑treeviewcell时,显示的为树编辑控件,需要继承treeview,同时实现idatagridvieweditingcontrol接口,实现以下方法:
public class treevieweditingcontrol : treeview, idatagridvieweditingcontrol { datagridview datagridview; private bool valuechanged = false; int rowindex; public treevieweditingcontrol() { try { //必须加roots.tree.nodes[].clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆 this.nodes.add(roots.tree.nodes[].clone() as treenode); this.selectednode = this.nodes[]; } catch (exception ex) { messagebox.show(ex.message); } } // implements the idatagridvieweditingcontrol.editingcontrolformattedvalue // property. public object editingcontrolformattedvalue { get { return this.selectednode.text; } set { if (value is string) { try { // this will throw an exception of the string is // null, empty, or not in the format of a date. this.selectednode = new treenode((string)value); } catch { // in the case of an exception, just use the // default value so we're not left with a null // value. this.selectednode = new treenode(""); } } } } // implements the // idatagridvieweditingcontrol.geteditingcontrolformattedvalue method. public object geteditingcontrolformattedvalue( datagridviewdataerrorcontexts context) { return editingcontrolformattedvalue; } // implements the // idatagridvieweditingcontrol.applycellstyletoeditingcontrol method. public void applycellstyletoeditingcontrol( datagridviewcellstyle datagridviewcellstyle) { this.font = datagridviewcellstyle.font; this.forecolor = datagridviewcellstyle.forecolor; this.backcolor = datagridviewcellstyle.backcolor; } // implements the idatagridvieweditingcontrol.editingcontrolrowindex // property. public int editingcontrolrowindex { get { return rowindex; } set { rowindex = value; } } // implements the idatagridvieweditingcontrol.editingcontrolwantsinputkey // method. public bool editingcontrolwantsinputkey( keys key, bool datagridviewwantsinputkey) { // let the treeviewpicker handle the keys listed. switch (key & keys.keycode) { case keys.left: case keys.up: case keys.down: case keys.right: case keys.home: case keys.end: case keys.pagedown: case keys.pageup: return true; default: return !datagridviewwantsinputkey; } } // implements the idatagridvieweditingcontrol.prepareeditingcontrolforedit // method. public void prepareeditingcontrolforedit(bool selectall) { // no preparation needs to be done. } // implements the idatagridvieweditingcontrol // .repositioneditingcontrolonvaluechange property. public bool repositioneditingcontrolonvaluechange { get { return false; } } // implements the idatagridvieweditingcontrol // .editingcontroldatagridview property. public datagridview editingcontroldatagridview { get { return datagridview; } set { datagridview = value; } } // implements the idatagridvieweditingcontrol // .editingcontrolvaluechanged property. public bool editingcontrolvaluechanged { get { return valuechanged; } set { valuechanged = value; } } // implements the idatagridvieweditingcontrol // .editingpanelcursor property. public cursor editingpanelcursor { get { return base.cursor; } } protected override void onafterexpand(treevieweventargs e) { base.onafterexpand(e); this.datagridview.columns[this.datagridview.currentcell.columnindex].width = this.width+; this.datagridview.rows[this.datagridview.currentcell.rowindex].height = this.height+; } protected override void onafterselect(treevieweventargs e) { // notify the datagridview that the contents of the cell // have changed. valuechanged = true; this.editingcontroldatagridview.notifycurrentcelldirty(true); base.onafterselect(e); } }
为了在不同类之间传递参数,定义一个全局静态类:
/// <summary> /// 静态类的静态属性,用于在不同class间传递参数 /// </summary> public static class roots { //从前台绑定树 public static treeview tree = null; }
完整代码为:
using system; using system.collections.generic; using system.linq; using system.text; using system.windows.forms; using system.componentmodel; namespace host_controls_in_windows_forms_datagridview_cells { /// <summary> /// 静态类的静态属性,用于在不同class间传递参数 /// </summary> public static class roots { //从前台绑定树 public static treeview tree = null; } /// <summary> /// host treeview in datagridview cell /// </summary> public class treeviewcolumn : datagridviewcolumn { public treeviewcolumn() : base(new treeviewcell()) { } [description("set treeview root in datagridview cell"), category("treeview")] public treeview _root { get{return roots.tree;} set{roots.tree=value;} } public override datagridviewcell celltemplate { get { return base.celltemplate; } set { // ensure that the cell used for the template is a treeviewcell. if (value != null && !value.gettype().isassignablefrom(typeof(treeviewcell))) { throw new invalidcastexception("must be a treeviewcell"); } base.celltemplate = value; } } } //---------------------------------------------------------------------- public class treeviewcell : datagridviewtextboxcell { public treeviewcell() : base() { //初始设置 } public override void initializeeditingcontrol(int rowindex, object initialformattedvalue, datagridviewcellstyle datagridviewcellstyle) { // set the value of the editing control to the current cell value. base.initializeeditingcontrol(rowindex, initialformattedvalue, datagridviewcellstyle); treevieweditingcontrol ctl = datagridview.editingcontrol as treevieweditingcontrol; // use the default row value when value property is null. if (this.value == null) { ctl.selectednode =new treenode( this.defaultnewrowvalue.tostring()); } else { ctl.selectednode = new treenode(this.value.tostring()); } } public override type edittype { get { // return the type of the editing control that calendarcell uses. return typeof(treevieweditingcontrol); } } public override type valuetype { get { // return the type of the value that calendarcell contains. return typeof(string); } } public override object defaultnewrowvalue { get { // use the current date and time as the default value. return ""; } } } //----------------------------------------------------------------- public class treevieweditingcontrol : treeview, idatagridvieweditingcontrol { datagridview datagridview; private bool valuechanged = false; int rowindex; public treevieweditingcontrol() { try { //必须加roots.tree.nodes[].clone() 否则报错 不能在多处增添或插入项,必须首先将其从当前位置移除或将其克隆 this.nodes.add(roots.tree.nodes[].clone() as treenode); this.selectednode = this.nodes[]; } catch (exception ex) { messagebox.show(ex.message); } } // implements the idatagridvieweditingcontrol.editingcontrolformattedvalue // property. public object editingcontrolformattedvalue { get { return this.selectednode.text; } set { if (value is string) { try { // this will throw an exception of the string is // null, empty, or not in the format of a date. this.selectednode = new treenode((string)value); } catch { // in the case of an exception, just use the // default value so we're not left with a null // value. this.selectednode = new treenode(""); } } } } // implements the // idatagridvieweditingcontrol.geteditingcontrolformattedvalue method. public object geteditingcontrolformattedvalue( datagridviewdataerrorcontexts context) { return editingcontrolformattedvalue; } // implements the // idatagridvieweditingcontrol.applycellstyletoeditingcontrol method. public void applycellstyletoeditingcontrol( datagridviewcellstyle datagridviewcellstyle) { this.font = datagridviewcellstyle.font; this.forecolor = datagridviewcellstyle.forecolor; this.backcolor = datagridviewcellstyle.backcolor; } // implements the idatagridvieweditingcontrol.editingcontrolrowindex // property. public int editingcontrolrowindex { get { return rowindex; } set { rowindex = value; } } // implements the idatagridvieweditingcontrol.editingcontrolwantsinputkey // method. public bool editingcontrolwantsinputkey( keys key, bool datagridviewwantsinputkey) { // let the treeviewpicker handle the keys listed. switch (key & keys.keycode) { case keys.left: case keys.up: case keys.down: case keys.right: case keys.home: case keys.end: case keys.pagedown: case keys.pageup: return true; default: return !datagridviewwantsinputkey; } } // implements the idatagridvieweditingcontrol.prepareeditingcontrolforedit // method. public void prepareeditingcontrolforedit(bool selectall) { // no preparation needs to be done. } // implements the idatagridvieweditingcontrol // .repositioneditingcontrolonvaluechange property. public bool repositioneditingcontrolonvaluechange { get { return false; } } // implements the idatagridvieweditingcontrol // .editingcontroldatagridview property. public datagridview editingcontroldatagridview { get { return datagridview; } set { datagridview = value; } } // implements the idatagridvieweditingcontrol // .editingcontrolvaluechanged property. public bool editingcontrolvaluechanged { get { return valuechanged; } set { valuechanged = value; } } // implements the idatagridvieweditingcontrol // .editingpanelcursor property. public cursor editingpanelcursor { get { return base.cursor; } } protected override void onafterexpand(treevieweventargs e) { base.onafterexpand(e); this.datagridview.columns[this.datagridview.currentcell.columnindex].width = this.width+; this.datagridview.rows[this.datagridview.currentcell.rowindex].height = this.height+; } protected override void onafterselect(treevieweventargs e) { // notify the datagridview that the contents of the cell // have changed. valuechanged = true; this.editingcontroldatagridview.notifycurrentcelldirty(true); base.onafterselect(e); } } }
当编辑无误后,可以在添加列的时候看到treeviewcolumn类型。此类型暴露出一个_root属性,可以绑定外部的一个带数据的treeview。
运行代码,单击单元格,进入编辑状态,可以看到如下界面:
以上内容是小编给大家介绍的c#自定义datagridviewcolumn显示treeview 的全部叙述,希望大家喜欢。