DataGridView展开与收缩功能实现_实用技巧

很多数据都有父节点与子节点,我们希望单击父节点的时候可以展开父节点下的子节点数据。

比如一个医院科室表,有父科室与子科室,点击父科室后,在父科室下面可以展现该科室下的所有子科室。

我们来说一下在DataGridView中如何实现这个功能。

首先,创建示例数据:

示例数据SQL

create table Department
(
 ID int identity(1,1) not null,
 DName varchar(20) null,
 DparentId int null,
 Dtelphone varchar(20) null,
 Dhospital varchar(50) null
) 

insert into Department values('门诊外室',1,'1111','XXX医院')
insert into Department values('门诊内科',1,'2222','XXX医院')
insert into Department values('门诊手术',1,'3333','XXX医院')
insert into Department values('门诊儿科',1,'4444','XXX医院')
insert into Department values('神经内室',2,'5555','XXX医院')
insert into Department values('神经外科',2,'6666','XXX医院')
insert into Department values('住院手术',2,'7777','XXX医院')
insert into Department values('住院康复',2,'8888','XXX医院')

其实思路很简单,就是在展开父节点的时候,在父节点下插入新的DataGridViewRow;收缩父节点的时候,在父节点下删除该子节点的DataGridViewRow。

为了简便,代码中的数据读取我都直接硬编码了。

加载父节点数据,除了数据库中的列外我还新加了两列:IsEx与EX。

private void DataGridBing(DataTable table)
    {
      if (table.Rows.Count > 0)
      {
        for (int i = 0; i < table.Rows.Count; i++)
        { 

          int k = this.dataGridView1.Rows.Add();
          DataGridViewRow row = this.dataGridView1.Rows[k];
          row.Cells["ID"].Value = table.Rows[i]["ID"];
          row.Cells["DName"].Value = table.Rows[i]["DName"];
          row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
          row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
          //用于显示该行是否已经展开
          row.Cells["IsEx"].Value = "false";
          //用于显示展开或收缩符号,为了简单我就直接用字符串了,其实用图片比较美观
          row.Cells["EX"].Value = "+";
        }
      }
    }

下面就是Cell的单击事件了,分别在事件中写展开的插入与收缩的删除.

插入子节点:

string isEx=this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value.ToString();
      if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx=="false")
      {
        string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
        DataTable table = GetDataTable("select * from Department where DparentId="+id);
        if (table.Rows.Count > 0)
        {
          //插入行
          this.dataGridView1.Rows.Insert(e.RowIndex+1, table.Rows.Count);
          for (int i = 0; i < table.Rows.Count; i++)
          {
            DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex + i+1];
            row.DefaultCellStyle.BackColor = Color.CadetBlue;
            row.Cells["ID"].Value = table.Rows[i]["ID"];
            row.Cells["DName"].Value = table.Rows[i]["DName"];
            row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
            row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
          }
        }
        //将IsEx设置为true,标明该节点已经展开
        this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "true";
        this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "-";

删除子节点:

if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx == "true")
      {
        string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
        DataTable table = GetDataTable("select * from Department where DparentId=" + id);
        if (table.Rows.Count > 0)
        {
          //利用Remove
          for (int i = 0; i < table.Rows.Count; i++)
          {
            foreach (DataGridViewRow row in this.dataGridView1.Rows)
            {
              if (row.Cells["ID"].Value.Equals(table.Rows[i]["ID"]))
              {
                this.dataGridView1.Rows.Remove(row);
              }
            }
          }
        }
        ////将IsEx设置为false,标明该节点已经收缩
        this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "false";
        this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "+";
      }

这里面通过比较ID来唯一确定一行,循环比较多,因为子节点是紧接着父节点的,我们可以确定子节点所在的行数,所以用RemoveAt()方法更好。

//利用RemoveAt
          for (int i = table.Rows.Count; i > 0; i--)
          {
            //删除行
            this.dataGridView1.Rows.RemoveAt(i + e.RowIndex);
          }

上面的做法是通过不断的插入与删除来实现,但这样与数据库的交互变得很频繁。更好的做法应该是插入一次,然后通过隐藏或显示行来实现我们的效果。

为此,我们还要在grid中新增两个列:

IsInsert:用来判断该行是否已经有插入子节点数据

RowCount:用来保存该行下插入的子节点数量。

在方法DataGridBing中,绑定数据时,应该再加一列:

//是否插入
row.Cells["IsInsert"].Value = "false";

而在增加节点的时候,我们要多做一个判断,如果IsInsert为false就插入数据,如果为true就显示数据

展开行

if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx=="false")
      {
        if (this.dataGridView1.Rows[e.RowIndex].Cells["IsInsert"].Value.ToString() == "false")
        {
          string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
          DataTable table = GetDataTable("select * from Department where DparentId=" + id);
          if (table.Rows.Count > 0)
          {
            //插入行
            this.dataGridView1.Rows.Insert(e.RowIndex + 1, table.Rows.Count);
            for (int i = 0; i < table.Rows.Count; i++)
            {
              DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex + i + 1];
              row.DefaultCellStyle.BackColor = Color.CadetBlue;
              row.Cells["ID"].Value = table.Rows[i]["ID"];
              row.Cells["DName"].Value = table.Rows[i]["DName"];
              row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
              row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
            }
            this.dataGridView1.Rows[e.RowIndex].Cells["IsInsert"].Value = "true";
            this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value = table.Rows.Count;
          }
        }
        else
        {
          //显示数据
          int RowCount = Convert.ToInt32(this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value);
          for (int i = 1; i <= RowCount; i++)
          {
            this.dataGridView1.Rows[e.RowIndex + i].Visible = true;
          }
        }
        //将IsEx设置为true,标明该节点已经展开
        this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "true";
        this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "-";
      }

收缩的时候,我们直接隐藏行就可以了.

收缩行

if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx == "true")
      {
        int RowCount = Convert.ToInt32(this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value);
        for (int i = 1; i <= RowCount; i++)
        {
          //隐藏行
          this.dataGridView1.Rows[e.RowIndex + i].Visible = false;
        }
        ////将IsEx设置为false,标明该节点已经收缩
        this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "false";
        this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "+";
      }

大家知道DataGridView是如何实现展开收缩的吧,希望大家不仅知道是如何实现的还要动手实验一番,才不枉小编辛苦整理此文章哦

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索datagridview展开
, datagridview收缩
datagridview添加行
js展开收缩、jquery展开收缩效果、点击展开收缩代码、ios cell点击展开收缩、jquery收缩展开菜单,以便于您获取更多的相关知识。

时间: 2024-10-26 22:47:29

DataGridView展开与收缩功能实现_实用技巧的相关文章

GridView多层嵌套和折叠与展开(修改适合自己使用)_实用技巧

Insus.NET近段时间应朋友的要求,写一个GridView多层嵌套和折叠与展开.这个功能的GridView多层嵌套没有问题,因为已经做了无限次数,但是折叠与展开的功能,却花上不少时间(网上找资料),虽找到资料可参考,还是了解明它,并修改适合自己程序使用.效果如下: 站点中多个页面使用,因此Insus.NET把它写在一个用户自定义控件ASCX上. 复制代码 代码如下: InsusMenu.ascx <%@ Control Language="VB" AutoEventWireu

.NET微信开发之PC 端微信扫码注册和登录功能实现_实用技巧

一.前言 先声明一下,本文所注重点为实现思路,代码及数据库设计主要为了展现思路,如果对代码效率有着苛刻要求的项目切勿照搬. 相信做过微信开发的人授权这块都没少做过,但是一般来说我们更多的是为移动端的网站做授权,确切来说是在微信端下做的一个授权.今天遇到的一个问题是,项目支持微信端以及 PC 端,并且开放注册.要求做到无论在 PC 端注册或者是在微信端注册之后都可以在另外一个端进行登录.也就是说无论 PC 或是微信必须做到"你就是你"(通过某种方式关联). 二.寻找解决方案 按传统的方式

asp.net Bundle功能扩展_实用技巧

前言 新建Asp.net MVC4项目的时候,在Global.asax.cs里面发现多了一句代码 BundleConfig.RegisterBundles(BundleTable.Bundles) google了以后终于弄清楚了这个的作用,发现这个东西确实非常实用,且功能强大,能够压缩合并js和CSS,但是目前的使用起来不是特别好,如果添加js或者css文件的话,需要修改BundleConfig的代码. 这里我自己简单修改了BundleConfig,对这个进行简单的扩展. 下面贴出代码: 先贴配

asp.net继承IHttpHandler接口实现给网站图片添加水印功能实例_实用技巧

本文实例讲述了asp.net继承IHttpHandler接口实现给网站图片添加水印功能.分享给大家供大家参考,具体如下: 先展示图片效果: 1. 在App_Code下添加类文件,命名为ImageSY 文件内容如下 public class ImageSY : IHttpHandler { public ImageSY() { // //TODO: 在此处添加构造函数逻辑 // } #region IHttpHandler 成员 public bool IsReusable { get { ret

.NET下为百度文本编辑器UEditor增加图片删除功能示例_实用技巧

百度的这个编辑器,的确挺好,但也有些,让人不如意的,如每次更新,本来有功能给搞没了,旧版本的代码又不能直接拿过来组合用,对用户来很是不爽.今天下载了目前最新版1.2.5为版本看更新记录,主要是对表格做个修改,我下载用上,我靠,上传图片的删除功能给取消了.把旧版本的删除代码拿过来,不好使,还得我慢慢研究,闹心啊,闹心,折磨我半天. 1.首先修改服务器端ueditor\net下的文件imageManager.ashx,增加图片删除的处理.如下代码的Add部分所示: 复制代码 代码如下: <%@ We

ASP.NET MVC分页和排序功能实现_实用技巧

分页和排序,应该是软件开发中,需要必知必会的技能了,对于分页,网上很多教程,当然,别人终究是别人的,只有自己理解,会了,并且吸收之后,再用自己的语言,传授出来,这才是硬道理.好了,废话说多了.现在我们进入正题:  这里,我打算使用EF Code-First方式分页控件就是用PagedList.MVC,来做分页,对于排序,实现的思路是,加载数据出来之后,默认是升序排序,然后我们点击一下相应的列标题,就按照该字段降序排序,查数据.思路明确了,就开始干吧!  1.首先新建一个空白的MVC项目,在Mod

asp.net分页功能实现_实用技巧

说一下实现分页的思路 这里的分页用到了一个组件 AspNetPage.dll,这个组件大家可以到网上去下载,我这里就不提供了 添加最近到工具箱中这样我们就可以像其他控件一样拖拽使用了 如图DataPage是在工具箱中的,至于怎么添加你们百度吧 拖拽到页面中如图 这个是我加完样式后显示的效果,怎么样是不是你们想要的了,如果不是你们还可以修改样式样式稍候奉上 先来看看要怎么使用 <webdiyer:AspNetPager ID="AspNetPager1" runat="s

ASP.NET MVC4之js css文件合并功能(3)_实用技巧

MVC4增加了一些新功能,接下来,我们来研究下MVC4中的新增功能,我们在新建一个MVC4项目的时候,会发现在项目下多出了一个App_Start文件夹,文件夹下面有4个文件,BundleConfig.cs,FilterConfig.cs,RouteConfig.cs,WebApiConfig.cs,其中BundleConfig.cs文件就是我们这一节要讲的的文件. 众所周知,浏览器在向服务器发送请求的时候,请求的文件连接数量是有限制的.使用BundleConfig可以将多个文件请求和并成一个请求

c#实现根据网络IP显示地理位置功能示例_实用技巧

用户信息表,是大多数系统都有的.我们也知道,通常都会有类似 注册IP 和 最后登录IP 这两个的字段,来存储用户注册时候的IP地址和最后登录的IP的地址. 获取这样的地址,在后台显示 xxx.xxx.xxx.xxx 的地址段,让人看到很不自然,根本就不知道具体地理位置. 现在我们就简单的实现一下这个功能. 用到了读取纯真IP数据库的公用组件QQWry.NET 这个组件,作者阿不.(谢谢他的共享) 还要去下载最新的纯真IP地址库,下载获得QQWry.dat 最后请出Js中的小靓妞,jquery-1