1. 程式人生 > WINDOWS開發 >WinForm 樹形列表(三級) 可展開,可摺疊

WinForm 樹形列表(三級) 可展開,可摺疊

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

            }
        }

這篇就這些