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

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

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

代码如下:

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

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

 public void AddChildnode(int mid, TreeNode pnode)
{
RoleHandle rh = new RoleHandle();
DataTable dm = rh.Menu_Texts_Type(); for (int i = ; i < dm.Rows.Count - ; i++)
{
if (int.Parse(dm.Rows[i]["Menu_Parent"].ToString()) == mid)
{
TreeNode cnode = new TreeNode();
cnode.Text = dm.Rows[i]["Menu_Text"].ToString();
cnode.Tag = int.Parse(dm.Rows[i]["Menu_ID"].ToString());
pnode.Nodes.Add(cnode);
//调用本方法,递归
AddChildnode(int.Parse(dm.Rows[i]["Menu_ID"].ToString()), cnode);
}
}
}

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

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

          private void RoleChanged()
{
RoleHandle rh = new RoleHandle();
int roleId = GetSelectedRoleId();
//循环遍历treeview1所有根节点
for (int i = ; i < treeView1.Nodes.Count; i++)
{
//查询数据库判断是否有该权限
if (rh.RoleMenuCheck(int.Parse(treeView1.Nodes[i].Tag.ToString()), roleId) != null && rh.RoleMenuCheck(int.Parse(treeView1.Nodes[i].Tag.ToString()), roleId).Rows.Count > )
{
//如果有权限,则勾选该节点
treeView1.Nodes[i].Checked = true;
}
else
{
treeView1.Nodes[i].Checked = false;
}
//调用递归的方法判断其子节点
TreeViewAllNodes(treeView1.Nodes[i], roleId);
}
}

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

  private void TreeViewAllNodes(TreeNode parentNode, int roleId)
{
RoleHandle rh = new RoleHandle();
foreach (TreeNode node in parentNode.Nodes)
{
if (rh.RoleMenuCheck(int.Parse(node.Tag.ToString()), roleId) != null && rh.RoleMenuCheck(int.Parse(node.Tag.ToString()), roleId).Rows.Count > )
{
node.Checked = true;
}
else
{
node.Checked = false;
}
if (node.Nodes.Count > )//如果该节点下还有子节点
{
//运用递归,调用改方法
TreeViewAllNodes(node, roleId);
}
}
}

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

 private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
//判断该节点状态(展开或折叠)
if (nodestate)
{
TreeNode node = e.Node;
if (node.Nodes.Count > )//包含子节点,实现子级联动
{
//实现子级联动的方法
SetTreeViewChecked(node);
}
if (node.Parent != null)//有父级菜单,实现父级联动
{
//实现父级联动的方法
SetParentNodeState(node);
}
nodestate = false;//修改节点状态
}
}

子级联动的方法如下:

 private void SetTreeViewChecked(TreeNode node)
{
if (node == null)
{
return;
}
if (node.Nodes.Count > )//判断该节点下有子节点
{
foreach (TreeNode item in node.Nodes)
{
item.Checked = node.Checked;
//调用该方法,递归
SetTreeViewChecked(item);
}
}
}

父级联动方法如下:

 private void SetParentNodeState(TreeNode node)
{
//定义变量用来设置父节点的选中情况,bool ck = false;假设子节点为全不选情况
bool ck = false;
TreeNode pn = node.Parent;
if (pn != null)
{
//假设所有子节点为全未选,循环判断是否有子节点选中
foreach (TreeNode item in pn.Nodes)
{
//如果有一个子节点是选中的,ck=true;
if (item.Checked)
{
ck = true;
break;
}
}
if (ck)
{
pn.Checked = true;
}
else
{
pn.Checked = false;
SetParentNodeState(pn);//递归
}
}
}

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

 //设置全局变量,用来接收节点的状态
private bool nodestate = false;
private void RoleMenuForm_Load(object sender, EventArgs e)
{
//在窗体加载事件中注册方法treeView1.AfterCheck
treeView1.AfterCheck += TreeView1_AfterCheck;
}
//treeView1.AfterCheck方法 private void TreeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
//改变节点状态
nodestate = true;
}

最新文章

  1. C#限速下载网络文件
  2. 本地预览图片html和js例子
  3. 关于ios的手势识别(GestureRecognizers)讲解
  4. FCKeditor文字编辑器
  5. Python CRM项目四
  6. JAVA_SE基础——4.path的临时配置&Classpath的配置
  7. Web Storage:浏览器端数据储存机制
  8. C#ComboBox绑定List
  9. NPOI 关于Excel的学习
  10. SonarQube(代码质量管理)环境搭建
  11. 2/17 笔记 n:字符串索引、切片、数据转换笔记
  12. php-编译模块2
  13. java⑧
  14. [转]Android开源测试框架学习
  15. form的method用get导致中文乱码
  16. LOJ#2082. 「JSOI2016」炸弹攻击 2(计算几何+双指针)
  17. 【黑金原创教程】 FPGA那些事儿 SignalTap II 调试技巧
  18. 475. Heaters 加热范围
  19. 如果你是后台开发者,InnoDB的小秘密,你应该知道
  20. python之路 模块,序列化,迭代器,生成器

热门文章

  1. sass(混合mixin的调用、@content)
  2. JS构造函数(便于理解,简易)
  3. 使用notebook 笔记(1)
  4. php提示undefined index的几种解决方法
  5. Orchard Core 文档翻译 (六)HTML
  6. SAP Fiori里两种锁机制(lock)的实现
  7. Eclipse Java常用快捷键(Eclipse Shortcut Keys for Java Top10)(转)
  8. C++11新特性之 std::forward(完美转发)
  9. BZOJ3053:The Closest M Points(K-D Teee)
  10. caffe 学习(1) —— Classification: Instant Recognition with Caffe