解决方案 »

  1.   

    那我反过来问你,如果用户想为此人添加几个村,你要怎么做?让用户逐个添加?说的更极端点,如果用户要做一次反选操作,取消现有的,选择没选的,你准备让用户执行多少次添加和删除?这样用户就会爽了?为用户添加权限(就是更改权限),这是系统管理员才有的权限,那当然是加载整个树结构了。用户本身没有修改权限的能力。根据用户权限,动态生成树的目的,是为了在当前用户下,对他权限范围内的节点进行选择和业务处理。
    当一棵树生成实例,有了root,全选、反选、取消选择,都是递归的问题,用js写个递归处理函数就可以解决了。整个问题的描述大概可以是这样:
    要从一棵完整的树中,生成一个子树,但是可能发生断层,如何处理断层问题,是拼接,还是怎样。
      

  2.   

    那么又回到上面那个问题,用户操作的是村还是区还是县,如果是村,那么只需要保留4级节点的checkbox,同时只保留有选中的4级目录的上级
      

  3.   


    估计是吧。
    举例:
    传入的参数是:gid的集合:10000    10221910  
     10000   (越秀区,pid= 2000000,是 2级)
    10221910(芳村,pid=999043,是 4级)
    传入的参数是可以区分gid的等级的,比如在gid前面添加(1,2,3,4代表typeid即可。使用的时候先截取出来)假如SQL语句是这样的,那么结果集将包含所有该pid下的数据记录,也包含了所有构建子树所需要的记录。select distinct *
    from member 
    start with pid in(10000,10221910)  and gid in(10000,10221910) 
    connect by prior  gid=pid;构建的过程就是:
    1.先构建没有断层的节点:
    先判断是否1级、2级、3级,然后构造成树根和树的第一层节点。
    2.处理有断层的节点:
    根据传入的权限集合,逐条记录,取它的父ID代表节点,向上回溯已生成的树,有祖先(包括自己)则不用管(因为祖先展开后肯定会把它加入到树),如果没有祖先,则把它添加到树根。有点混乱,不过能理清思路了。非常感谢!
      

  4.   

    结贴。附上最终解决的源码。        //第一次展开时,加载子节点
            function nodeLoad(node) {
                Coolite.AjaxMethods.NodeLoad(node.id, {
                    success: function (result) {
                        var data = eval("(" + result + ")");
                        node.loadNodes(data);
                    },
                    failure: function (errorMsg) {
                        Ext.Msg.alert("错误提示", errorMsg);
                    }
                });
            }
    <ext:TreePanel ID="TreePanel1" runat="server" 
    Title="请勾选要导出数据的网格,然后点击【下载】按钮,进行下载。"
                                            AutoScroll="true">
               <Listeners>
                         <BeforeLoad Fn="nodeLoad" />
                                            </Listeners>
                                            <TopBar>
                                                <ext:Toolbar ID="Toolbar1" runat="server">
                                                    <Items>
                                                        <ext:Button ID="btnFanSel" runat="server" Text="取消选中" Icon="House">
                                                            <Listeners>
                                                                <Click Fn="selectOtherNodes" />
                                                            </Listeners>
                                                        </ext:Button>
                                                        <ext:Button ID="btnSeeSel" runat="Server" Text="查看已选节点" Icon="House">
                                                            <Listeners>
                                                                <Click Fn="seeSelectNodes" />
                                                            </Listeners>
                                                        </ext:Button>
                                                        <ext:Button ID="btnDaoChu" runat="server" Text=" 下载 " Icon="DiskDownload">
                                                            <Listeners>
                                                                <Click Fn="btnDownload_Click" />
                                                            </Listeners>
                                                        </ext:Button>
                                             <ext:Button ID="btnHelp" runat="server" Text=" 帮助 " Icon="Help">
                                         <Listeners>
                                                   <Click Fn="btnHelp_Click" />
                                          </Listeners>
                                     </ext:Button>
                             </Items>
                       </ext:Toolbar>
             </TopBar>
    </ext:TreePanel>上面是extjs的控件代码,关键在这一行:
    <BeforeLoad Fn="nodeLoad" />
    每次展开时加载节点,都会触发这个函数,进行动态加载。
    后台代码:
       /// <summary>
            /// 展开一个结点时,加载其所有子节点,返回json给前台
            /// </summary>
            /// <param name="nodeID"></param>
            /// <returns></returns>
            [AjaxMethod]
            public string NodeLoad(string nodeID)
            {
                Coolite.Ext.Web.TreeNodeCollection nodes = new Coolite.Ext.Web.TreeNodeCollection();
                if (!string.IsNullOrEmpty(nodeID))
                {
                    DataRow[] dr = dtAll.Select("pid='" + nodeID + "'", "gname asc");
                    Coolite.Ext.Web.AsyncTreeNode childNode;
                    for (int i = 0; i < dr.Length; i++)
                    {
                        childNode = new AsyncTreeNode();
                        childNode.NodeID = dr[i]["gid"].ToString();
                        childNode.Text = dr[i]["gname"].ToString();                    if (dr[i]["typeid"].ToString() == "网格") //是网格,是叶子结点
                        {
                            childNode.Checked = ThreeStateBool.False;
                            childNode.AllowChildren = false;
                            childNode.Expandable = ThreeStateBool.False;
                        }
                        else      //不是网格,是内部结点
                        {
                            childNode.Checked = ThreeStateBool.Undefined;
                            childNode.AllowChildren = true;
                            childNode.Expandable = ThreeStateBool.True;
                        }
                        nodes.Add(childNode);
                    }
                }
                return nodes.ToJson();
            }
    在最开始页面加载时,树根是不存在的,需要在Page_Load函数中先构建树根,这时候构建的根、第一层节点、等等都不会出发上面js的NodeLoad函数。
            protected void Page_Load(object sender, EventArgs e)
            {
                emp = ComContext.GetCurrentUser();
                if (emp == null)
                {
                    Response.Redirect("../blank.htm");
                }
                string[] per = emp.PERMISSIONAREA.Split(';');
                if (per.Length == 0)
                {
                    Ext.Msg.Show(new MessageBox.Config
                    {
                        Title = "提示信息",
                        Message = "你没有任何权限!",
                        Buttons = MessageBox.Button.OK,
                        Icon = (MessageBox.Icon)Enum.Parse(typeof(MessageBox.Icon), "WARNING")
                    });
                    this.Dispose(); //关闭页面
                }
                //从数据库获取所有有权限的结点
                dtAll = bllTree.getPermisssionList(emp.PERMISSIONAREA).Tables[0];            BindRoot();//加载节点
            }
            //绑定根节点和一级结点,页面加载时调用
            private void BindRoot()
            {
                this.TreePanel1.Root.Clear();            Coolite.Ext.Web.TreeNode rootNode = new Coolite.Ext.Web.TreeNode();
                rootNode.NodeID = "200000000";
                rootNode.Text = "广州";
                rootNode.Checked = ThreeStateBool.Undefined;
                rootNode.AllowChildren = true;
                rootNode.Expanded = true;            TreePanel1.Root.Add(rootNode);
               .........
    }