场景

效果

示例源码下载

https://download.csdn.net/download/badao_liumang_qizhi/11593399

实现

新建一个Winform程序,然后在页面上拖拽一个DataGridView和一个Button。

布局如下:

其中DataGridView点击右上角新增列,然后添加两列。

右击项目-添加--类

其中后三个字段属性是必须的,Level代表节点层次,ChildList代表子节点。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace TreeGridViewTestOnly
{public class Person{public int id;public int Id{get { return id; }set { id = value; }}public string password;public string Password{get { return password; }set { password = value; }}private int level;public int Level{get { return level; }set { level = value; }}private bool isExpanded;public bool IsExpanded{get { return isExpanded; }set { isExpanded = value; }}private List<Person> childList;public List<Person> ChildList{get { return childList; }set { childList = value; }}}
}

双击窗体进入窗体的加载事件中

private void Form1_Load(object sender, EventArgs e){//首先生成数据this.GenerateData();//然后生成列this.GenerateClo();}

在生成数据的方法中

 /// <summary>/// 生成数据/// </summary>private void GenerateData() {for (int i = 0; i < 100; i++){Person p1 = new Person() { Id = i, Password = "密码" + i, Level = 1 };for (int j = 0; j < 10; j++){Person p2 = new Person() { Id = j, Password = "密码" + j, Level = 2 };for (int k = 0; k < 10; k++){Person p3 = new Person() { Id = k, Password = "密码" + k, Level = 3 };if (p2.ChildList == null){p2.ChildList = new List<Person>();}p2.ChildList.Add(p3);}if (p1.ChildList == null){p1.ChildList = new List<Person>();}p1.ChildList.Add(p2);}personList.Add(p1);}}

如果是三层树结构就这样三层循环,几层机构依次类推。

在生成列的方法中

private void GenerateClo(){this.dataGridView1.ReadOnly = true;this.dataGridView1.AllowUserToAddRows = false;this.dataGridView1.AllowUserToDeleteRows = false;this.dataGridView1.AllowUserToOrderColumns = false;this.dataGridView1.AllowUserToResizeRows = false;this.dataGridView1.AllowUserToResizeColumns = false;#region 影响性能this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;this.dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;this.dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;#endregionthis.dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None;//this.dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;this.dataGridView1.RowHeadersVisible = false;this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;this.dataGridView1.VirtualMode = true;this.dataGridView1.CellValueNeeded -= dataGridView1_CellValueNeeded;this.dataGridView1.CellValueNeeded += dataGridView1_CellValueNeeded;this.dataGridView1.Columns.Clear();int colWidth = 100;DataGridViewImageColumn colImg = new DataGridViewImageColumn();colImg.HeaderText = String.Empty;colImg.Width = 20;DataGridViewTextBoxColumn colId = new DataGridViewTextBoxColumn();colId.Name = "colId";colId.HeaderText = "序号";colId.MinimumWidth = 160;DataGridViewTextBoxColumn colA = new DataGridViewTextBoxColumn();colA.HeaderText = "ID";colA.Width = colWidth;DataGridViewTextBoxColumn colB = new DataGridViewTextBoxColumn();colB.HeaderText = "密码";colB.Width = colWidth;this.dataGridView1.Columns.Add(colId);this.dataGridView1.Columns.Add(colA);this.dataGridView1.Columns.Add(colB);foreach (DataGridViewColumn col in this.dataGridView1.Columns){col.ReadOnly = true;}this.dataGridView1.CellMouseClick += dataGridView1_CellMouseClick;}

其中生成列所用到的方法

private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e){if (e.RowIndex >= this.dataGridView1.RowCount || e.RowIndex > this.personList.Count){return;}Random r = new Random();r.NextDouble();Person record = this.personList[e.RowIndex];object[] values = new object[] { record.Id, record.id, record.password };e.Value = values[e.ColumnIndex];if (e.ColumnIndex == 0){Person currRecord = this.personList[e.RowIndex];if (currRecord.ChildList != null && currRecord.ChildList.Count > 0){if (currRecord.IsExpanded){e.Value = GenerateSpace(currRecord.Level) + "  [-]  " + values[e.ColumnIndex];}else{e.Value = GenerateSpace(currRecord.Level) + "  [+]  " + values[e.ColumnIndex];}}else{e.Value = GenerateSpace(currRecord.Level + 1) + values[e.ColumnIndex];}}}/// <summary>/// 根据节点级别生成要显示的空格数/// </summary>/// <param name="level"></param>/// <returns></returns>public string GenerateSpace(int level){int step = 5;StringBuilder sb = new StringBuilder();for (int i = 0; i < step * (level - 1); i++){sb.Append(" ");}return sb.ToString();}void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e){if (dataGridView1.Columns[e.ColumnIndex].Name == "colId"){Console.WriteLine("MouseClick...");if (this.personList[e.RowIndex].ChildList != null && this.personList[e.RowIndex].ChildList.Count > 0){if (this.personList[e.RowIndex].IsExpanded){//this.lst2.RemoveRange(e.RowIndex + 1, this.lst2[e.RowIndex].ChildList.Count);this.RecursiveRemove(this.personList, e.RowIndex);this.personList[e.RowIndex].IsExpanded = false;this.ShowData(this.personList);}else{this.personList.InsertRange(e.RowIndex + 1, this.personList[e.RowIndex].ChildList);this.personList[e.RowIndex].IsExpanded = true;this.ShowData(this.personList);}this.dataGridView1.Rows[0].Selected = false;this.dataGridView1.Rows[e.RowIndex].Selected = true;}}}/// <summary>/// 递归移除/// </summary>/// <param name="lst"></param>/// <param name="index"></param>/// <param name="count"></param>public void RecursiveRemove(List<Person> lst, int index){int count = GetAllExpandChildCount(lst[index]);lst.RemoveRange(index + 1, count);}public int GetAllExpandChildCount(Person r){if (r.ChildList != null && r.ChildList.Count > 0){int cnt = 0;if (r.IsExpanded){cnt = r.ChildList.Count;for (int i = 0; i < r.ChildList.Count; i++){cnt += GetAllExpandChildCount(r.ChildList[i]);}}r.IsExpanded = false;return cnt;}else{return 0;}}

然后声明一个全局变量存放数据

public partial class Form1 : Form{public List<Person> personList = new List<Person>();

在Button的点击事件中

  private void button1_Click(object sender, EventArgs e){this.ShowData(this.personList);}public void ShowData(List<Person> lst){int recordCount = lst.Count;this.dataGridView1.Rows.Clear();this.dataGridView1.RowCount = recordCount;}

完整示例代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace TreeGridViewTestOnly
{public partial class Form1 : Form{public List<Person> personList = new List<Person>();public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){//首先生成数据this.GenerateData();//然后生成列this.GenerateClo();}/// <summary>/// 生成数据/// </summary>private void GenerateData() {for (int i = 0; i < 100; i++){Person p1 = new Person() { Id = i, Password = "密码" + i, Level = 1 };for (int j = 0; j < 10; j++){Person p2 = new Person() { Id = j, Password = "密码" + j, Level = 2 };for (int k = 0; k < 10; k++){Person p3 = new Person() { Id = k, Password = "密码" + k, Level = 3 };if (p2.ChildList == null){p2.ChildList = new List<Person>();}p2.ChildList.Add(p3);}if (p1.ChildList == null){p1.ChildList = new List<Person>();}p1.ChildList.Add(p2);}personList.Add(p1);}}/// <summary>/// 生成列/// </summary>private void GenerateClo(){this.dataGridView1.ReadOnly = true;this.dataGridView1.AllowUserToAddRows = false;this.dataGridView1.AllowUserToDeleteRows = false;this.dataGridView1.AllowUserToOrderColumns = false;this.dataGridView1.AllowUserToResizeRows = false;this.dataGridView1.AllowUserToResizeColumns = false;#region 影响性能this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;this.dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;this.dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;#endregionthis.dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None;//this.dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;this.dataGridView1.RowHeadersVisible = false;this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;this.dataGridView1.VirtualMode = true;this.dataGridView1.CellValueNeeded -= dataGridView1_CellValueNeeded;this.dataGridView1.CellValueNeeded += dataGridView1_CellValueNeeded;this.dataGridView1.Columns.Clear();int colWidth = 100;DataGridViewImageColumn colImg = new DataGridViewImageColumn();colImg.HeaderText = String.Empty;colImg.Width = 20;DataGridViewTextBoxColumn colId = new DataGridViewTextBoxColumn();colId.Name = "colId";colId.HeaderText = "序号";colId.MinimumWidth = 160;DataGridViewTextBoxColumn colA = new DataGridViewTextBoxColumn();colA.HeaderText = "ID";colA.Width = colWidth;DataGridViewTextBoxColumn colB = new DataGridViewTextBoxColumn();colB.HeaderText = "密码";colB.Width = colWidth;this.dataGridView1.Columns.Add(colId);this.dataGridView1.Columns.Add(colA);this.dataGridView1.Columns.Add(colB);foreach (DataGridViewColumn col in this.dataGridView1.Columns){col.ReadOnly = true;}this.dataGridView1.CellMouseClick += dataGridView1_CellMouseClick;}private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e){if (e.RowIndex >= this.dataGridView1.RowCount || e.RowIndex > this.personList.Count){return;}Random r = new Random();r.NextDouble();Person record = this.personList[e.RowIndex];object[] values = new object[] { record.Id, record.id, record.password };e.Value = values[e.ColumnIndex];if (e.ColumnIndex == 0){Person currRecord = this.personList[e.RowIndex];if (currRecord.ChildList != null && currRecord.ChildList.Count > 0){if (currRecord.IsExpanded){e.Value = GenerateSpace(currRecord.Level) + "  [-]  " + values[e.ColumnIndex];}else{e.Value = GenerateSpace(currRecord.Level) + "  [+]  " + values[e.ColumnIndex];}}else{e.Value = GenerateSpace(currRecord.Level + 1) + values[e.ColumnIndex];}}}/// <summary>/// 根据节点级别生成要显示的空格数/// </summary>/// <param name="level"></param>/// <returns></returns>public string GenerateSpace(int level){int step = 5;StringBuilder sb = new StringBuilder();for (int i = 0; i < step * (level - 1); i++){sb.Append(" ");}return sb.ToString();}void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e){if (dataGridView1.Columns[e.ColumnIndex].Name == "colId"){Console.WriteLine("MouseClick...");if (this.personList[e.RowIndex].ChildList != null && this.personList[e.RowIndex].ChildList.Count > 0){if (this.personList[e.RowIndex].IsExpanded){//this.lst2.RemoveRange(e.RowIndex + 1, this.lst2[e.RowIndex].ChildList.Count);this.RecursiveRemove(this.personList, e.RowIndex);this.personList[e.RowIndex].IsExpanded = false;this.ShowData(this.personList);}else{this.personList.InsertRange(e.RowIndex + 1, this.personList[e.RowIndex].ChildList);this.personList[e.RowIndex].IsExpanded = true;this.ShowData(this.personList);}this.dataGridView1.Rows[0].Selected = false;this.dataGridView1.Rows[e.RowIndex].Selected = true;}}}/// <summary>/// 递归移除/// </summary>/// <param name="lst"></param>/// <param name="index"></param>/// <param name="count"></param>public void RecursiveRemove(List<Person> lst, int index){int count = GetAllExpandChildCount(lst[index]);lst.RemoveRange(index + 1, count);}public int GetAllExpandChildCount(Person r){if (r.ChildList != null && r.ChildList.Count > 0){int cnt = 0;if (r.IsExpanded){cnt = r.ChildList.Count;for (int i = 0; i < r.ChildList.Count; i++){cnt += GetAllExpandChildCount(r.ChildList[i]);}}r.IsExpanded = false;return cnt;}else{return 0;}}private void button1_Click(object sender, EventArgs e){this.ShowData(this.personList);}public void ShowData(List<Person> lst){int recordCount = lst.Count;this.dataGridView1.Rows.Clear();this.dataGridView1.RowCount = recordCount;}}
}

C#中实现一个TreeGridView(树形表格)附源码下载相关推荐

  1. C#中实现视频播放器窗体程序(附源码下载)

    场景 效果 实现 新建窗体程序,然后从工具箱中拖拽DataGridView控件,然后在控件右上角点击新增列,设置好每列 的Name属性和Headertext属性. 新建Video类 项目-右击-新增- ...

  2. php实现电子签名,php实现往pdf中加数字签名操作示例【附源码下载】

    本文实例讲述了php实现往pdf中加数字签名操作.分享给大家供大家参考,具体如下: //======================================================== ...

  3. Winforn中DevExpress的TreeList中显示某路径下的所有目录和文件(附源码下载)

    场景 Winform中DevExpress的TreeList的入门使用教程(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  4. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  5. Redis在Java中的使用及连接数据库(附源码)

    Redis在Java中的使用及连接数据库(附源码) 引言: 本文主要分享了Redis如何在IDEA中部署,运行:模拟加入Redis的操作: 文章目录 Redis在Java中的使用及连接数据库(附源码) ...

  6. 美!视差滚动在图片滑块中的应用【附源码下载】

    视差滚动(Parallax Scrolling)已经被广泛应用于网页设计中,这种技术能够让原本平面的网页界面产生动感的立体效果.下面分享的这个图片滑块效果是难得一见的结合视差滚动的例子,之前的文章给大 ...

  7. 美!视差滚动特效在图片滑块中的应用【附源码下载】

    视差滚动(Parallax Scrolling)已经被广泛应用于网页设计中,这种技术能够让原本平面的网页界面产生动感的立体效果.下面分享的这个图片滑块效果是难得一见的结合视差滚动的例子,之前的文章给大 ...

  8. 我搭建了一个随机「毒鸡汤」语录网站附源码下载

    小伙伴们注意:公众号的推送机制不再按照时间前后推送了,微信公众号信息流乱序.君哥建议大家把科技毒瘤君公众号置顶(设为星标⭐),以便第一时间看到推送,非常感谢~,方法如下图: 1 演示效果 ★ 遇到喜欢 ...

  9. vscode中安装webpack_leaflet-webpack 入门开发系列一初探篇(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载 webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址w ...

最新文章

  1. 《机器人与数字人:基于MATLAB的建模与控制》——2.3节指数映射和k过程
  2. neoterm如何安装python_NeoTerm下载-NeoTerm(安卓终端)下载v2.1.0-be8d6cf 安卓版-西西软件下载...
  3. Python学习(四)列表与列表操作
  4. LINQ中的动态排序
  5. java创建一个程序把输入字符串的大小写互换_8 编写程序,从键盘接收一个字符串,对字符串中的字母进行大小写互转...
  6. SpringBoot启动流程分析(四):IoC容器的初始化过程
  7. 特定视图呈现时发生的事件顺序
  8. python 检测文件更新失败_依赖错误,检测更新失败,提示这个
  9. 解决桌面右键无NVIDIA控制面板选项
  10. fw325r虚拟服务器,fw325r无线路由器设置
  11. php attr属性,jquery 获取 自定义属性(attr 和 prop)
  12. YUI中一些方法总结
  13. 有向图的强连通分量(SCC)
  14. 2022年系统集成项目管理工程师考试知识点:项目成本管理
  15. 游戏辅助制作核心--植物大战僵尸逆向之召唤僵尸call(九)
  16. 学习ios(必看经典)牛人40天精通iOS开发的学习方法
  17. 操作系统:动态内存分区分配算法实现(C++)
  18. background-size cover和contain的区别
  19. 1.3RK3288积累之命令1
  20. srt文件解析 c语言,c语言标准库函数srt排序的介绍与使用.docx

热门文章

  1. WINCE下的MINGW交叉编译环境下内存崩溃地址的查找方法。
  2. if语句 power query_PowerQuery学习:认识M函数
  3. map 长度_Python实用教程系列——高阶函数Map、Filter、Reduce
  4. springaop事务逻辑原理_架构师:一篇文章掌握——Spring 事务管理
  5. 拉格朗日c语言实验报告,拉格朗日插值法C语言的实现(实验报告)(9页)-原创力文档...
  6. android怎么长按一张图片保存到相册_instagram怎么保存图片?
  7. post 返回代码_减少冗长代码,利用DDT轻松分离测试数据
  8. html绘制头像原样教程,CSS实例教程:创意CSS3头像展示教程
  9. c语言周传生教材答案,C语言程序设计与实践(普通高等教育“十二五”规划教材)...
  10. java socket 如何设置so_keepalive属性_socket通信的KeepAlive设定