Winform开发常用控件之TreeView菜单导航和权限用法

时间:2024-03-18 07:39:19

TreeView一个很棒的控件,我们在做WEB开发时常常犯困的一个东东。当然这里介绍winform里面的用法唠。

先介绍几个属性吧,CheckBoxes设置为true的话树形节点前面会出现checkbox勾选框、ImageList绑定树形里面的图标(界面上放一个Imgelist控件,绑定上即可)、ShowLines(树形展开时显示线条)等等

哦,这个方法好,this.MenutreeView.ExpandAll();即Treeview加载后全部展开。

下面先介绍一个简单的菜单用法

1、TreeView节点的设置和选取节点

TreeView静态节点的设置方法很简单,主要用在软件的快捷导航中。贴图,可以设置多级节点,每个节点设置Name和Text属性即可,如果觉得不美观,可以放一些图标。

本例中的图标是用ImageList绑定到里面的,还是比较简单。

设置好节点后,就可以写节点的事件了,贴代码

 /// <summary>
        /// 树形目录菜单
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// AfterSelect事件是点击节点时的事件
        private void MenutreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string nodeselect = MenutreeView.SelectedNode.Name;
            switch (nodeselect)
            {
                case "用户管理": ShowUsermanager(); break;
                case "竞赛项目管理": ShowItemFrm(); break;
                case "参赛单位管理": ShowDepartFrm(); break;
                case "运动员信息": ShowMemberInfoFrm(); break;
                case "代表队名单": ShowMatchTeamFrm(); break;
                case "随机分组": ShowRandomGroupFrm(); break;
                case "分组信息": ShowGroupInfoFrm(); break;
                case "评分管理": ShowPointFrm(); break;
                case "成绩管理": ShowScoreFrm(); break;
                default: break;

            }
        }

看到了吧,还是比较简单,case到以后,执行相应的方法即可,本例中主要是show一些窗口。

2、TreeView动态绑定及获取勾选值

这里介绍一个权限的示例,本例是将选中的节点放置在listbox中

上图拿到了text和name两个值

      private void BindTreeView()
        {
            treeView1.LabelEdit = false;//不可编辑
            //添加结点
            TreeNode root = new TreeNode();
            root.Text = "根节点";
            root.Name = "All";
            //一级
            TreeNode node1 = new TreeNode();
            node1.Text = "新增";
            node1.Name = "Add";
            TreeNode node2 = new TreeNode();
            node2.Text = "编辑";
            node2.Name = "Edit";
            //二级
            TreeNode node11 = new TreeNode();
            node11.Text = "新增管理员";
            node11.Name = "AddManager";
            TreeNode node12 = new TreeNode();
            node12.Text = "新增普通用户";
            node12.Name = "AddUser";
            TreeNode node21 = new TreeNode();
            node21.Text = "编辑管理员";
            node21.Name = "EditManager";
            TreeNode node22 = new TreeNode();
            node22.Text = "编辑普通用户";
            node22.Name = "EditUser";
            //二级加入一级
            node1.Nodes.Add(node11);
            node1.Nodes.Add(node12);
            node2.Nodes.Add(node21);
            node2.Nodes.Add(node22);
            //一级加入根
            root.Nodes.Add(node1);
            root.Nodes.Add(node2);
            //
            treeView1.Nodes.Add(root);
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            foreach (TreeNode node in treeView1.Nodes)//实际上treeVIew1里面只有1个根节点,所以要用递归方法
            {
                SetTreeViewList(node);
            }           
        }
        //递归方法
        private void SetTreeViewList(TreeNode node)
        {
            if (node.Checked)
            {
                listBox1.Items.Add(node.Text + "&" + node.Name);
            }
            if (node.Nodes.Count > 0)
            {
                foreach (TreeNode cnode in node.Nodes)
                {                    
                    SetTreeViewList(cnode);//递归
                }
            }           
        }

由于Treeview遍历只能拿到一个根节点(这点大家可以做实验看看),因此必须使用递归才能找到其他子节点,下面再补充一点就是子节点全部选中后父节点自动选中,父节点选中后子节点全部选中

贴代码,下面这段接着上面的即可 

 //勾选的事件,必须写在AfterCheck事件中
        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action == TreeViewAction.ByMouse)//这句还是比较重要哦,如果没有的话就会陷入死循环
            {
                if (e.Node.Checked)
                {
                    //选中其子节点
                    setChildNodeCheckedState(e.Node, true);
                    //如果有父节点,选中其所有父节点
                    if (e.Node.Parent != null)
                    {
                        setParentNodeCheckedState(e.Node, true);
                    }
                }
                else
                {
                    //取消其子节点
                    setChildNodeCheckedState(e.Node, false);
                    //取消其所有父节点
                    if (e.Node.Parent != null)
                    {
                        setParentNodeCheckedState(e.Node, false);
                    }
                }
            }
        }
        //子节点递归
        private void setChildNodeCheckedState(TreeNode currNode, bool state)
        {
            TreeNodeCollection nodes = currNode.Nodes;
            if (nodes.Count > 0)
                foreach (TreeNode tn in nodes)
                {
                    tn.Checked = state;
                    setChildNodeCheckedState(tn, state);
                }
        }
        //父节点递归
        private void setParentNodeCheckedState(TreeNode currNode, bool state)
        {
            TreeNode parentNode = currNode.Parent;
            parentNode.Checked = state;
            if (currNode.Parent.Parent != null)
            {
                setParentNodeCheckedState(currNode.Parent, state);
            }
        }

上个图,看下效果

如此之类的做法可以直接将权限做到窗口的按钮上,然后自己写一个基类Form根据权限来判断菜单、按钮是否显示、是否可用等,所有的窗体继承自这个基类窗体就可以实现一劳永逸的权限控制了。具体示例有时间了奉上。