我们可以自定义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 的全部叙述,希望大家喜欢。
dy("nrwz");
查看更多关于C#自定义DataGridViewColumn显示TreeView的详细内容...