欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#自定义DataGridViewColumn显示TreeView

程序员文章站 2022-04-10 09:57:10
我们可以自定义datagridview的datagridviewcolumn来实现自定义的列,下面介绍一下如何通过扩展datagridviewcolumn来实现一个tree...

我们可以自定义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接口,实现以下方法:

C#自定义DataGridViewColumn显示TreeView

 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);
   }
  }
 }

C#自定义DataGridViewColumn显示TreeView

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

C#自定义DataGridViewColumn显示TreeView

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

C#自定义DataGridViewColumn显示TreeView

以上内容是小编给大家介绍的c#自定义datagridviewcolumn显示treeview 的全部叙述,希望大家喜欢。