Datagridview 实现树形列表的效果
菜单文字都做了改动,防止泄露公司的密码,毕竟签了协议的
代码中有两个字典类型
// 记录父级菜单编号及是一级父节点还是二级父节点 Dictionary<string, int> _dictIsPMenu; // 是否展开 Dictionary<string, bool> _dictPMenuExpand;
首先需要绑定一个对应数据的泛型集合,其他的数据暂时没试过
Dictionary<string, int> _dictIsPMenu = new Dictionary<string, int>(); Dictionary<string, bool> _dictPMenuExpand = new Dictionary<string, bool>(); List<M_Menu> temp = 某个数据接口 List<M_Menu> topMenuList = temp.Where(a => a.MM_PMenID == GuidEmpty).ToList(); List<M_Menu> menuList = new List<M_Menu>(topMenuList.ToArray());//深拷贝 List<M_Menu> secondMenuList; List<M_Menu> thirdMenuList; int index = 0; // 循环*节点 for (int i = 0; i < topMenuList.Count; i++) { // 查询*节点下的子节点 secondMenuList = temp.Where(a => a.MM_PMenID == topMenuList[i].MM_MenID).ToList(); // 向数据字典添加数据 _dictIsPMenu.Add(topMenuList[i].MM_MenID, 1);
// true 为默认展开 _dictPMenuExpand.Add(topMenuList[i].MM_MenID, true); // 循环对应子节点 for (int j = 0; j < secondMenuList.Count; j++) { menuList.Insert(++index, secondMenuList[j]); // 二级子节点 thirdMenuList = temp.Where(a => a.MM_PMenID == secondMenuList[j].MM_MenID).ToList(); if (thirdMenuList.Count > 0) { _dictIsPMenu.Add(secondMenuList[j].MM_MenID, 2); _dictPMenuExpand.Add(secondMenuList[j].MM_MenID, true); for (int k = 0; k < thirdMenuList.Count; k++) { menuList.Insert(++index, thirdMenuList[k]); } } } index++; } // 此数据只会查出二级子菜单的数据 dgvMenuList.DataSource = menuList;
然后在datagridview的CellPoint 中写入画图的代码
// 判断是否是需要画图的列 if (e.RowIndex >= 0 && dgvMenuList.Columns[e.ColumnIndex].DataPropertyName == "MM_MenName") { string menuId = this.dgvMenuList.Rows[e.RowIndex].Cells["MM_MenID"].Value.ToString(); string menuName = this.dgvMenuList.Rows[e.RowIndex].Cells["MM_MenName"].Value.ToString(); string pMenuId = this.dgvMenuList.Rows[e.RowIndex].Cells["MM_PMenID"].Value.ToString(); Image img; Rectangle newRect; if (_dictIsPMenu.ContainsKey(menuId)) { img = _dictPMenuExpand[menuId] ? Properties.Resources.tree_icon_two : Properties.Resources.tree_icon_one; newRect = new Rectangle( e.CellBounds.X + 3, e.CellBounds.Y + e.CellBounds.Height / 2 - img.Height / 2, img.Width, img.Height); //判断当前节点是不是二级父节点 if (_dictIsPMenu[menuId] == 2) { newRect.X += 10; } } else { img = Properties.Resources.tree_icon_three; newRect = new Rectangle( e.CellBounds.X + 3 + 10, e.CellBounds.Y + e.CellBounds.Height / 2 - img.Height / 2, img.Width, img.Height); //判断当前父节点是不是二级父节点 if (_dictIsPMenu[pMenuId] == 2) { newRect.X += 10; } } using (Brush gridBrush = new SolidBrush(this.dgvMenuList.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor)) { using (Pen gridLinePen = new Pen(gridBrush, 2)) { // 擦除单元格 e.Graphics.FillRectangle(backColorBrush, e.CellBounds); //绘制背景色:如果选中那就用设置的背景色,否则用默认白色背景色 if (dgvMenuList.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected) { e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(172, 204, 253)), e.CellBounds.X , e.CellBounds.Y , e.CellBounds.Width - 1, e.CellBounds.Height - 1); } else { e.Graphics.FillRectangle(new SolidBrush(dgvMenuList.DefaultCellStyle.BackColor), e.CellBounds.X, e.CellBounds.Y, e.CellBounds.Width - 1, e.CellBounds.Height - 1); } //划线 Point p1 = new Point(e.CellBounds.Left + e.CellBounds.Width, e.CellBounds.Top); Point p2 = new Point(e.CellBounds.Left + e.CellBounds.Width, e.CellBounds.Top + e.CellBounds.Height); Point p3 = new Point(e.CellBounds.Left, e.CellBounds.Top + e.CellBounds.Height); Point[] ps = new Point[] { p1, p2, p3 }; e.Graphics.DrawLines(gridLinePen, ps); //画图标 e.Graphics.DrawImage(img, newRect); //画字符串 e.Graphics.DrawString(menuName.ToString(), this.Font, Brushes.Black, newRect.X + 3 * 2 + img.Width, e.CellBounds.Top + Font.GetHeight(), StringFormat.GenericDefault); e.Handled = true; } } }
然后实现点击展开折叠,通过datagridview 的CellClick事件,如果这个事件觉得不好也可用换一个事件,只要能获取到对应行列就行
private void dgvMenuList_CellClick(object sender, DataGridViewCellEventArgs e) { int rowIndex = e.RowIndex; int colIndex = e.ColumnIndex; // 点中序号和标题列就返回 if (colIndex == 0 || rowIndex < 0) { return; } string menuId = dgvMenuList.Rows[e.RowIndex].Cells["MM_MenID"].Value.ToString(); // 判断当前菜单ID是否是父级菜单 if (_dictIsPMenu.ContainsKey(menuId)) { string menuName = dgvMenuList.Rows[e.RowIndex].Cells["MM_MenName"].Value.ToString(); gpObjChecks.Controls.Clear(); for (int i = e.RowIndex + 1; i < dgvMenuList.RowCount; i++) { string pMenuId = dgvMenuList.Rows[i].Cells["MM_PMenID"].Value.ToString(); string tempMenuId = dgvMenuList.Rows[i].Cells["MM_MenID"].Value.ToString(); bool state = !_dictPMenuExpand[menuId]; // *父级 if (_dictIsPMenu[menuId] == 1) { //判断是否到下一个*父级菜单了 if (pMenuId == GuidEmpty) { _dictPMenuExpand[menuId] = state; break; } dgvMenuList.Rows[i].Visible = state; _dictPMenuExpand[tempMenuId] = state; // 当前父菜单不是下一个*父菜单,但是是下一级父菜单 if (pMenuId != menuId) { dgvMenuList.Rows[i].Visible = _dictPMenuExpand[pMenuId]; } } // 次级父级 else { //判断是否到下一个次级父级菜单了 if (pMenuId != menuId) { _dictPMenuExpand[menuId] = state; break; } else { dgvMenuList.Rows[i].Visible = state; } } // 最后一行的特殊处理 if (i == dgvMenuList.RowCount - 1) { _dictPMenuExpand[menuId] = state; dgvMenuList.Rows[i].Visible = state; } } } else { string pMenuId = dgvMenuList.Rows[e.RowIndex].Cells["MM_PMenID"].Value.ToString(); M_Menu menu = _menuBLL.GetMenu(pMenuId); } }
这篇就这些