做角色菜单权限时用到treeview控件做树状显示菜单,简单总结了一下用法:

1.在winform窗体中拖入treeview控件,注意修改属性CheckBoxes属性为true,即在节点旁显示复选框

2.后台动态加载数据库数据绑定到treeview上,子节点使用递归添加

代码如下:

 1 //循环添加treeview节点
 2             for (int i = 0; i < dm.Rows.Count - 1; i++)//dm是数据库查出的数据表
 3             {
 4                 //添加父节点(一级菜单)
 5                 if (int.Parse(dm.Rows[i]["Menu_Type"].ToString()) == 0)
 6                 {
 7                     TreeNode pnode = new TreeNode();
 8                     pnode.Text = dm.Rows[i]["Menu_Text"].ToString();
 9                     pnode.Tag = int.Parse(dm.Rows[i]["Menu_ID"].ToString());
10                     treeView1.Nodes.Add(pnode);
11                     //调用方法,添加子级菜单
12                     AddChildnode(int.Parse(dm.Rows[i]["Menu_ID"].ToString()), pnode);
13                 }
14             }

添加子级菜单的方法如下:

 1 public void AddChildnode(int mid, TreeNode pnode)
 2         {
 3             RoleHandle rh = new RoleHandle();
 4             DataTable dm = rh.Menu_Texts_Type();
 5 
 6             for (int i = 0; i < dm.Rows.Count - 1; i++)
 7             {
 8                 if (int.Parse(dm.Rows[i]["Menu_Parent"].ToString()) == mid)
 9                 {
10                     TreeNode cnode = new TreeNode();
11                     cnode.Text = dm.Rows[i]["Menu_Text"].ToString();
12                     cnode.Tag = int.Parse(dm.Rows[i]["Menu_ID"].ToString());
13                     pnode.Nodes.Add(cnode);
14                     //调用本方法,递归
15                     AddChildnode(int.Parse(dm.Rows[i]["Menu_ID"].ToString()), cnode);
16                 }
17             }
18         }

 

3.获取角色对应的权限,有权限则勾选,没有权限则不管

我同样封装了一个方法,方法代码如下:

 1          private void RoleChanged()
 2         {
 3             RoleHandle rh = new RoleHandle();
 4             int roleId = GetSelectedRoleId();
 5             //循环遍历treeview1所有根节点
 6             for (int i = 0; i < treeView1.Nodes.Count; i++)
 7             {
 8                     //查询数据库判断是否有该权限
 9                 if (rh.RoleMenuCheck(int.Parse(treeView1.Nodes[i].Tag.ToString()), roleId) != null && rh.RoleMenuCheck(int.Parse(treeView1.Nodes[i].Tag.ToString()), roleId).Rows.Count > 0)
10                 {
11                     //如果有权限,则勾选该节点
12                     treeView1.Nodes[i].Checked = true;
13                 }
14                 else
15                 {
16                     treeView1.Nodes[i].Checked = false;
17                 }
18                  //调用递归的方法判断其子节点
19                 TreeViewAllNodes(treeView1.Nodes[i], roleId);
20             }
21         }    

判断子节点菜单是否有权限的方法(即判断子节点是否应勾选)

 1  private void TreeViewAllNodes(TreeNode parentNode, int roleId)
 2         {
 3             RoleHandle rh = new RoleHandle();
 4             foreach (TreeNode node in parentNode.Nodes)
 5             {
 6                 if (rh.RoleMenuCheck(int.Parse(node.Tag.ToString()), roleId) != null && rh.RoleMenuCheck(int.Parse(node.Tag.ToString()), roleId).Rows.Count > 0)
 7                 {
 8                     node.Checked = true;
 9                 }
10                 else
11                 {
12                     node.Checked = false;
13                 }
14                 if (node.Nodes.Count > 0)//如果该节点下还有子节点
15                 {
16                     //运用递归,调用改方法
17                     TreeViewAllNodes(node, roleId);
18                 }
19             }
20         }

4.使用鼠标单击treeview节点事件,实现点击某treeview节点时的子节点和父节点联动,代码如下:

 1 private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
 2          {
 3             //判断该节点状态(展开或折叠)
 4             if (nodestate)
 5             {
 6                 TreeNode node = e.Node;
 7                 if (node.Nodes.Count > 0)//包含子节点,实现子级联动
 8                 {
 9                      //实现子级联动的方法
10                      SetTreeViewChecked(node);
11                  }
12                  if (node.Parent != null)//有父级菜单,实现父级联动
13                  {
14                     //实现父级联动的方法
15                    SetParentNodeState(node);
16                  }
17                 nodestate = false;//修改节点状态
18              }
19          }

子级联动的方法如下:

 1 private void SetTreeViewChecked(TreeNode node)
 2         {
 3             if (node == null)
 4             {
 5                 return;
 6             }
 7             if (node.Nodes.Count > 0)//判断该节点下有子节点
 8             {
 9                 foreach (TreeNode item in node.Nodes)
10                 {
11                     item.Checked = node.Checked;
12                     //调用该方法,递归
13                     SetTreeViewChecked(item);
14                 }
15             }
16         }

父级联动方法如下:

 1 private void SetParentNodeState(TreeNode node)
 2         {
 3             //定义变量用来设置父节点的选中情况,bool ck = false;假设子节点为全不选情况
 4             bool ck = false;
 5             TreeNode pn = node.Parent;
 6             if (pn != null)
 7             {
 8                 //假设所有子节点为全未选,循环判断是否有子节点选中
 9                 foreach (TreeNode item in pn.Nodes)
10                 {
11                     //如果有一个子节点是选中的,ck=true;
12                     if (item.Checked)
13                     {
14                         ck = true;
15                         break;
16                     }
17                 }
18                 if (ck)
19                 {
20                     pn.Checked = true;
21                 }
22                 else
23                 {
24                     pn.Checked = false;
25                     SetParentNodeState(pn);//递归
26                 }
27             }
28         }

补充说明一下,鼠标单击treeview节点事件有点坑,折叠或展开节点时也会触发该事件,所以我使用了TreeView1_AfterCheck事件解决了这个问题

 1 //设置全局变量,用来接收节点的状态 
 2 private bool nodestate = false;
 3         private void RoleMenuForm_Load(object sender, EventArgs e)
 4         {
 5          //在窗体加载事件中注册方法treeView1.AfterCheck
 6          treeView1.AfterCheck += TreeView1_AfterCheck;
 7         }
 8         //treeView1.AfterCheck方法
 9 
10         private void TreeView1_AfterCheck(object sender, TreeViewEventArgs e)
11         {
12             //改变节点状态
13             nodestate = true;
14         }

 

posted on 2019-05-24 14:18  爱写随记的代码搬运工  阅读(793)  评论(0编辑  收藏  举报