ASP.NET 树结构及权限树的设计

 

1.树形结构的设计

在开发ASP.NET的项目中,有许多项目用到的树形结构,其中有些树形结构相对复杂,也有简单的,但无论是简单的树形结构还是复杂的树形结构,有着好的结构对于性能和稳定性都有着很大的作用。比如你的树结构的数据很大,如果是采用比较死的方式一次性加载进来那么你在加载这棵树的时候就是相当的耗时了,性能就大大的打了折扣。

我在设计这棵树时首先加载的是一级的节点,即想要显示的最外层的节点,然后通过点击展开节点的事件去加载其子节点,即可以根据用户的需要才去加载相关的子节点;可能在节点中我们可能会在节点中设计节点的右键菜单,比如“刷新”节点的菜单等,所以刷新也是重新加载节点的一个过程,下面将分别通过图示和简单的例子去讲解。

下面将以一颗商品的树来简单讲解,比如商品有着电器、文具、食品等类型。

    

1)        页面代码:

    <asp:TreeView ID="treeView" runat="server" ShowLines="true" EnableClientScript="false" Height="100%" OnTreeNodeExpanded="treeNodeExpanded">

<Nodes>

     <asp:TreeNode Text="商品" Value="sp01" Expanded="true" ImageUrl="节点图片"    NavigateUrl="点击节点的连接地址"></asp:TreeNode>                </Nodes>

</asp:TreeView>

2)        后台代码:

l        初始化节点

if (!IsPostBack)

        {

            InitTreeView();

} 

       private void InitTreeView()

{

AddCollectNode(treeView.Nodes[0]); //即给“商品”添加子节点

}

l        添加节点

private void AddCollectNode(TreeNode baseNode)

{

    //清空父节点下的所有子节点

baseNode.ChildNodes.Clear();

//获取父节点的子节点集合

。。。。。。

//判断子节点集合数是否大于零,即是否存在子节点

。。。。。

//如果存在子节点,循环添加子节点

         foreach (遍历子集合)

         {

             TreeNode node = new TreeNode(子节点);

      node.NavigateUrl = 子节点连接                        baseNode.ChildNodes.Add(node);//父节点添加子节点

             node.Collapse();

}

//如果不存在子节点,则添加一个空节点,给父节点添加空节点是为了能让父节点折起,可以让父节点有展开事件,可以对父节点进行数据刷新。

         TreeNode tn = new TreeNode("[ 暂无数据 ]", "0");

         tn.NavigateUrl = "javascript:void(0);";

 baseNode.ChildNodes.Add(tn);

}

l        节点展开事件

    protected void treeNodeExpanded (object sender, TreeNodeEventArgs e)

    {

        RefreshTreeNode(e.Node); //调用刷新节点方法

}

l        刷新节点

private void RefreshTreeNode(TreeNode baseNode)

{

    AddCollectNodebaseNode);

}

//你可能会问为什么还要一个刷新的方法,而不在展开事件时直接调用的是刷新的方法,因为你在做刷新操作时可以判断节点的类型,即在刷新方法中可以有一个逻辑的判断过程,当然了这也是根据你的需要的了。

2. 页面异步刷新树

      

OK,上面简单分析的是在页面中如果去展现一颗树,且让这棵树有着比较好的性能了,当然树还有很多东西值得去探讨和学习的,比如下面要简单说的是,在框架或不同页面中去刷新这棵树。比如,我使用的下面这样的一个页面框架:

比如当前的操作是我在页面框架的右边的页面做了添加一个商品的操作,那么就得让左边的树能自动去刷新看到添加的商品的节点。

要实现这样的功能,采用的是在页面上添加一个隐藏按钮,在其它页面去触发这个隐藏的按钮,通过隐藏按钮的事件去执行刷新这棵树。流程图如下:

                  

 

还是来看下代码吧!~

 

1)        页面代码:

     <div style="display: none;">

       <asp:Button ID="refreshBt" runat="server" OnClick="refreshBt_onclick" />

    </div>

2)        后台代码:

    /// <summary>

    /// 异步刷新TreeView按钮

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

protected void refreshBt_onclick(object sender, EventArgs e)

{

   refresh_TreeNodes(treeView.Nodes[0]) 

}

//刷新方法

protected void refresh_TreeNodes(TreeNode baseNode)

{

         TreeNodeCollection childnNods = baseNode.ChildNodes;

        ArrayList expandedNodes = new ArrayList();

 

        SaveExpandedTreeNodes(childnNods, expandedNodes); //记录保存展开的节点

        if (baseNode.Expanded == true)

        {

            baseNode.Expanded = false;

            baseNode.Expanded = true;

 

            foreach (object id in expandedNodes) //判断展开节点集合中的节点是否和树节点对应,如果是,则做收缩和展开操作

            {

                TreeNode node = FindNode(Convert.ToInt32(id), baseNode, "mark");

                if (node != null)

                {

                    node.Expanded = false;

                    node.Expanded = true;

                }

            }

        }

}

 

 

    /// <summary>

    /// 记录保存展开的节点

    /// </summary>

    /// <param name="childNods"></param>

    /// <param name="expandedNodes"></param>

    private void SaveExpandedTreeNodes(TreeNodeCollection childNods, ArrayList expandedNodes)

    {

        while (childNods != null && childNods.Count > 0)

        {

            for (int ix = 0; ix < childNods.Count; ix++)

            {

                TreeNode node = childNods[ix];

                if (node.Expanded == true)

                {

                    expandedNodes.Add(node.Value);

                    SaveExpandedTreeNodes(node.ChildNodes, expandedNodes);

                }

            }

            return;

        }

    }

 

 

    private TreeNode FindNode(int id, TreeNode baseNode, string mark)

    {

        TreeNode myNode = null;

        foreach (TreeNode tn in baseNode.ChildNodes)

        {

            int myId = Convert.ToInt32(tn.Value);

            if (id != myId)

            {

                myNode = FindNode(id, tn);

                if (myNode != null)

                {

                    break;

                }

            }

            else

            {

                if (tn.ChildNodes.Count != 0)

                {

                    myNode = tn;

                    break;

                }

                else

                {

                    continue;

                }

            }

        }

 

        return myNode;

    }

 

    private TreeNode FindNode(int id, TreeNode tn)

    {

        TreeNode myNode = null;

        foreach (TreeNode t in tn.ChildNodes)

        {

            int myId = Convert.ToInt32(t.Value);

            if (id != myId)

            {

                myNode = FindNode(id, t);

                if (myNode != null)

                {

                    break;

                }

            }

            else

            {

                if (t.ChildNodes.Count != 0)

                {

                    myNode = t;

                    break;

                }

                else

                {

                    continue;

                }

            }

        }

 

        return myNode;

    }

3.权限树的设计

权限树结构的设计也可以和上面的树那样了,但在权限树中会更多用到的是节点的选择,即checkbox,当选择一个父节点时还要把其子节点也选择,如果通过JS是可以去实现这个级联操作的,但问题是在treeView中节点的checkbox是不返回服务器端的,即你点击checkbox服务器端是不响应的,所以很难去记录选择的节点。对于记录选择的节点也有多种,一种可以采用JS去实现页面的级联,在后台采用编辑树节点的方法,另一种是没选择一个节点时响应服务器,再去记录节点。还是看看代码吧!

<asp:TreeView ID="tieeView" runat="server" ShowLines="true" EnableClientScript="false"

    Height="100%" OnTreeNodeCheckChanged=" NodeCheckChanged">

     <Nodes>

          <asp:TreeNode Text="商品" Value="unit05" Expanded="true"></asp:TreeNode>

         </Nodes>

   </asp:TreeView>

1)    后台:

tieeView.ShowCheckBoxes = TreeNodeTypes.All;

tieeView.Attributes.Add("onclick", "postBackByObject()");

2)       JS去实现级联及服务器响应

       //checkbox选择父节点及子节点,并返回服务器处理

       function postBackByObject()

       {

           var obj = window.event.srcElement;

           var treeNodeFound = false;

           var checkedState;

           if (obj.tagName == "INPUT" && obj.type == "checkbox")

           {

               //JS控制选择子节点

               var treeNode = obj;

               checkedState = treeNode.checked;

               do

               {

                    obj = obj.parentElement;

               }

               while (obj.tagName != "TABLE")

                  var parentTreeLevel = obj.rows[0].cells.length;

                  var parentTreeNode = obj.rows[0].cells[0];

                  var tables = obj.parentElement.getElementsByTagName("TABLE");

                  var numTables = tables.length

               if (numTables >= 1)

               {

                   for (i=0; i < numTables; i++)

                   {

                       if (tables[i] == obj)

                       {

                           treeNodeFound = true;

                              i++;

                           if (i == numTables)

                           {

                                    return;

                           }

                       }

                       if (treeNodeFound == true)

                       {

                            var childTreeLevel = tables[i].rows[0].cells.length;

                            if (childTreeLevel > parentTreeLevel)

                            {

                                var cell = tables[i].rows[0].cells[childTreeLevel - 1];

                                var inputs = cell.getElementsByTagName("INPUT");

                                inputs[0].checked = checkedState;

                            }

                            else

                            {

                                    return;

                             }

                       }

                   }

               }

           }     

       }

</script>

 

 

3)      选择checkbox响应服务器端

function postBackByObject()

{

        __doPostBack("","");

}

 

 

以上是个人在项目开发中经常用到的一些简单的东东,感兴趣的朋友可以一起探讨学习!~

 

 

声明:以上是个人在项目中经常用到的一些东东,在这是想和大家分享,对于我现在来说也是个学习的过程,可能以上的东西对于牛人或从事软件行业多年的人来说算是小菜一碟吧!~但我想上面的思想对于新人来说也是一个好的参考或学习过程吧,简单的难的技术问题都需要来丰富网络资源,给未接触过的人来说也是个支持!~牛人来了,希望你轻轻的离开,大不必留下什么鄙视的话,谢谢!~本人也是在不断的学习,谢绝转载时因为看到许多的商业性的网站转载了还带有不良的东东,谈不上“太自恃过高”!~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ASP.NET MVC 实现权限管理可以采用以下方式: 1. 角色和权限的定义:在系统中定义不同的角色和相应的权限,如管理员、普通用户等。可以通过数据库表或配置文件的方式进行定义。 2. 登录认证:用户在系统中进行登录时,验证用户名和密码的正确性,并根据认证结果进行相应的处理。可以使用 ASP.NET Identity 或自定义的身份验证方式。 3. 授权:在每个控制器或操作方法上定义访问所需的角色或权限。通过使用 ASP.NET MVC 提供的 [Authorize] 属性,只有具有相应角色或权限的用户才能访问该操作。 4. 视图层控制:在视图层,根据用户的角色或权限隐藏或显示相应的功能或菜单,以保证用户只能看到和操作自己有权限的内容。 5. 用户管理界面:提供一个用户管理界面,管理员可以在该界面中添加、删除或修改用户的角色或权限。可以使用 ASP.NET Identity 提供的功能,也可以自定义用户管理界面。 6. 审计日志:记录用户的操作日志,并存储到数据库中,方便后期的审计和追踪。可以使用 ASP.NET MVC 提供的框架或自定义的方式进行日志记录。 7. 异常处理:在发生权限相关的异常时,进行适当的异常处理,如跳转到错误页面或返回相应的错误信息,保证系统的安全性和稳定性。 通过以上这些步骤,可以有效实现ASP.NET MVC的权限管理功能,确保只有具备相应权限的用户才能访问系统的特定功能和资源。同时,管理员可以方便地管理用户的角色和权限,确保系统的安全性和可控性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值