WinForm 樹形列表(三級) 可展開,可摺疊
阿新 • • 發佈:2020-05-30
Datagridview 實現樹形列表的效果
選單文字都做了改動,防止洩露公司的密碼,畢竟簽了協議的
程式碼中有兩個字典型別
// 記錄父級選單編號及是一級父節點還是二級父節點 Dictionary<string,int> _dictIsPMenu; // 是否展開 Dictionary<string,bool> _dictPMenuExpand;
首先需要繫結一個對應資料的泛型集合,其他的資料暫時沒試過
Dictionary<string,int> _dictIsPMenu = newDictionary<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 = newList<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,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.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); } }
這篇就這些