当前位置:编程学习 > C#/ASP.NET >>

TreeView做权限树(动态绑定数据),Check框选择后如何获取该Node值?(跟页面执行顺序太有关系了,绝对值得thinking)附上代码,请高人

最近在做的一个BS系统,其中有个页面权限管理的页面
想用TreeView来搞定,思路如下:
=======================================================================
相关控件:
1.DropDownList:DDLRolers(用于选择角色)
2.TreeView:TVRolerMenu(根据角色来从数据库动态显示相应的页面权限)
3.Button:BtnSaveRolerMenu(根据TreeView中的选择框来分配相应的页面权限)
4.Label;Label1(用于调试用,点保存按钮后显示对应角色的页面权限和)
=======================================================================
数据库的结构我就不贴了
主要问题是:动态绑定TreeView后无法获取选择框打钩的Node结点的值,分析了一下,应该是页面执行顺序的问题,但又好像是TreeView的Bug,请高手帮我看看
 protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            selectValue = "0";
        }
        ShowPage();
    }
    protected void ShowPage()
    {
        ShowRoler();
        ShowRolerMenu();
    }
    protected void ShowRoler()
    {
        rm.BoundRoler("M_Roler", "Select * From M_Roler", DDLRolers, "roler_name", "roler_id");
        DDLRolers.Items.Insert(0,new ListItem("请选择角色","0")); 
    }
    protected void ShowRolerMenu()
    {
        rm.BoundRolerMenu(TVRolerMenu, selectValue);
    }
  
    protected void DDLRolers_SelectedIndexChanged(object sender, EventArgs e)
    {
        selectValue = DDLRolers.SelectedItem.Value.ToString();
        isSaved = false;
        Label1.Text = "";
    }

    protected void GetCheckNode(TreeView Tview)//获得TreeView中已选框的值
    {
        foreach (TreeNode node in Tview.CheckedNodes )
        {
            Label1.Text = node.Text + "|" + Label1.Text;
        }
    }
   //保存后显示相关角色有权使用的页面值
    protected void BtnSaveRolerMenu_Click(object sender, EventArgs e)
    {
        isSaved = true;
        GetCheckNode(TVRolerMenu);
    } --------------------编程问答-------------------- UPUP --------------------编程问答-------------------- try:
if (!IsPostBack)
{
            selectValue = "0";
           ShowPage();

 }
--------------------编程问答-------------------- lazyfish(呆呆虫):没用,试过,谢谢关注

我看到了差不多的贴子:
======================================================================
困扰俺了一个多月的难题,求各们高手出手相肋。(有关权限,树形菜单)
http://topic.csdn.net/t/20050118/14/3734767.html
======================================================================
其中有位兄弟这们说的:我觉得应该就是我要表达的,他比我表达的专业

如果你的CheckBox的Checked状态是在cs(即服务器端)初始的,那么在js(客户端   )所做的修改是不会影响到服务器端的,所以你可以这样,把Checked状态初始全部用js来完成。这样就可以了。
=======================================================================

--------------------编程问答-------------------- 你在绑定TVRolerMenu时,设置TVRolerMenu.Tag = 值;
在AfterCheck事件中
                           if(e.Node.Checked == true)   
{       
if(e.Node.Nodes.Count > 0)
{
for(int i = 0; i < e.Node.Nodes.Count; i++)   
{   
e.Node.Nodes[i].Checked = true;     
}   
}
}   
else   
{   
if(e.Node.Nodes.Count > 0)
{
for(int i = 0; i < e.Node.Nodes.Count; i++)   
{   
e.Node.Nodes[i].Checked = false;     
}     
}


最后用递归方法获得值(比如使用逗号分割)
                   public static void GetCheckedNode(TreeNodeCollection tnc, ref string strNodeTag)
{
foreach(TreeNode node in tnc)
{
if(node.Checked)
{
if(!IsDirecotry(node))
{
strNodeTag = strNodeTag + node.Tag.ToString() + ",";
}
}
GetCheckedNode(node.Nodes, ref strNodeTag);
}
} --------------------编程问答-------------------- shoutor(www.mouxiao.com)兄:AfterCheck事件没有啊,你是不是在CS程序中写的啊? --------------------编程问答-------------------- treeview的取值是要进行递归的,不然只能取到第一层
    Function GetNode(ByVal TV As Microsoft.Web.UI.WebControls.TreeView)
        Dim i As Integer
        Dim rs As String
        Dim myNode As Microsoft.Web.UI.WebControls.TreeNode
        For i = 0 To TV.Nodes.Count - 1
            myNode = TV.Nodes(i)
            If myNode.CheckBox = True And myNode.Checked Then
                rs = rs & myNode.NodeData & "#"
            End If
            If myNode.Nodes.Count > 0 Then
                rs = rs & GetNode(myNode)
            End If
        Next
        If rs <> "" Then
            Return Left(rs, Len(rs) - 1)
        End If
    End Function
    Function GetNode(ByVal nodes As Microsoft.Web.UI.WebControls.TreeNode)
        Dim i As Integer
        Dim rs As String
        rs = ""
        Dim myNode As Microsoft.Web.UI.WebControls.TreeNode
        For i = 0 To nodes.Nodes.Count - 1
            myNode = nodes.Nodes(i)
            If myNode.CheckBox = True And myNode.Checked Then
                rs = rs & myNode.NodeData & "#"
            End If
            If myNode.Nodes.Count > 0 Then
                rs = rs & GetNode(myNode)
            End If
        Next
        If rs <> "" Then
            Return rs
        End If
    End Function
返回的是#分割的字符串
并且分成两个函数,可以从整个树下面取,也可以从某一节点下面取 --------------------编程问答-------------------- UP UP --------------------编程问答-------------------- autopostback=true
随时刷新 --------------------编程问答-------------------- sleepcraft(越学越不懂):其实这个不是重点。你的方法和我的方法不一样
foreach (TreeNode node in Tview.CheckedNodes )//checkednodes是表示已checked的Node
        {
            Label1.Text = node.Text + "|" + Label1.Text;
        }
最主要的是下面这句话:
================================================================================
如果你的CheckBox的Checked状态是在cs(即服务器端)初始的,那么在js(客户端   )所做的修改是不会影响到服务器端的,所以你可以这样,把Checked状态初始全部用js来完成。这样就可以了。
--------------------编程问答-------------------- TreeView2.Nodes.Clear()


        Dim conn As String = System.Configuration.ConfigurationManager.ConnectionStrings("znhConnectionStringall").ToString
        Dim sqlf As String = "select * from mainmenu"

        Dim daf As New SqlDataAdapter(sqlf, conn)
        Dim dsf As New DataSet
        daf.Fill(dsf)
        Dim i As Integer
        For i = 0 To dsf.Tables(0).Rows.Count - 1
            Dim td1 As New TreeNode
            td1.Text = dsf.Tables(0).Rows(i).Item(1).ToString
            TreeView2.Nodes.Add(td1)
            td1.Checked = True

            Dim sqlc As String = "select * from childmenu where menu_id=" & dsf.Tables(0).Rows(i).Item(0) & ""
            Dim da2 As New SqlDataAdapter(sqlc, conn)
            Dim ds2 As New DataSet
            da2.Fill(ds2)
            Dim j As Integer
            For j = 0 To ds2.Tables(0).Rows.Count - 1
                Dim td2 As New TreeNode
                td2.Text = ds2.Tables(0).Rows(j).Item(2).ToString
                td1.ChildNodes.Add(td2)

                Dim sqlx As String = "select * from usermenu where [name]='" & DropDownList2.SelectedItem.ToString & "'"
                Dim dax As New SqlDataAdapter(sqlx, conn)
                Dim dsx As New DataSet
                dax.Fill(dsx)
                Dim a As Integer
                For a = 0 To dsx.Tables(0).Rows.Count - 1
                    If td2.Text = dsx.Tables(0).Rows(a).Item(2).ToString Then
                        td2.Checked = True

                    End If
                Next

            Next
        Next
--------------------编程问答-------------------- 如何将Checked状态全部用Js来完成?
思路:在后台先将数据库中的相关字段读出来,然后传值到JS,再用JS来做Checked?
是不是说我手动点CheckBox,后台无法读出来?要用JS来触发某个CheckBox? --------------------编程问答-------------------- ziyulin0311(echo)兄弟,您这是啥意思啊 --------------------编程问答-------------------- up --------------------编程问答-------------------- 只是不明白你为什么要用JS来赋值,既然是体现数据库的内容,在后台来赋值不是更方便吗 --------------------编程问答-------------------- TO:sleepcraft,因为这个页面是用来给某个角色分配相应权限的
用TreeView来加载所有权限,根据角色权限表在后台将CheckBox设定来True Or false
同时前台可能改变CheckBox的状态,点保存后又回传至后台再到数据库
================================================================================
如果你的CheckBox的Checked状态是在cs(即服务器端)初始的,那么在js(客户端   )所做的修改是不会影响到服务器端的,所以你可以这样,把Checked状态初始全部用js来完成。这样就可以了。 --------------------编程问答-------------------- 那么,按照你的要求,完全放到后台执行都没有问题啊
从后台读取数据后,你前台所做的更改也不会影响到服务器端
同样可以达到点保存后回传至后台再到数据库
===============================================
当然,按照你所说的思路也是一种方法,也许效率上会有不同 --------------------编程问答-------------------- 如果是JS方法的话就爱莫能助了 --------------------编程问答-------------------- 另外我看了下你说的哪个帖子,他用JS来实现的主要原因是说如果在后台赋值的话那么checked的状态无法改变
事实上可以的,完全没有问题,他的代码我没仔细看,但在我做的项目中,类似的地方有好几个,都是完全没有问题的 --------------------编程问答-------------------- To:sleepcraft(越学越不懂)
哈哈,我是越说越糊涂了。
完全放到后台执行都没有问题啊----有点偏题了
我最想知道的我却一直没表达清楚
=============================================================================
顺序:
1:TreeView从后台绑定数据,显示在页面中
2: 我在前台通过页面修改数据(如某个NODE的CheckBox选中或不选中)
3: 点保存,先将已Checked(Node.Checked = true)的node值读出来
4: 根据3做相关数据库操作
--------------------编程问答-------------------- Dim conn1 As SqlConnection
        Dim connstr As String
        Dim comm As SqlCommand
        Dim commdel As SqlCommand
        connstr = System.Configuration.ConfigurationManager.ConnectionStrings("znhConnectionStringall").ToString
        conn1 = New SqlConnection(connstr)
        Dim sql As String = "select max(admin_qx) from admin"
        Dim adapter As New SqlDataAdapter(sql, conn1)
        Dim dataset As New DataSet
        adapter.Fill(dataset)

        'Response.Write(dataset.Tables(0).Rows(0).Item(0))
        ' Response.End()

        Dim a As Integer
        a = dataset.Tables(0).Rows(0).Item(0) + 1
        ' Response.Write(a)
        ' Response.End()
        conn1.Open()
        commdel = New SqlCommand("delete usermenu where name='" & DropDownList2.SelectedItem.ToString & "'", conn1)
        commdel.ExecuteNonQuery()





        For Each node As TreeNode In TreeView2.CheckedNodes
            'Label1.Text += "<li> " & node.Value
            comm = New SqlCommand("insert into usermenu (usermenu,qx,name) values('" & node.Value & "','" & a & "','" & DropDownList2.SelectedItem.ToString & "')", conn1)
            comm.ExecuteNonQuery()
        Next


        conn1.Close()

        conn1.Open()
        Dim comm1 As SqlCommand
        comm1 = New SqlCommand("update admin set admin_qx='" & a & "' where admin_name='" & DropDownList2.SelectedItem.ToString & "' ", conn1)
        comm1.ExecuteNonQuery()
        conn1.Close()

这是保存checked数据,刚刚给你的是显示动态绑定,(vb.net)写法 --------------------编程问答-------------------- 现在的问题是步骤3,读不出来啊
--------------------编程问答-------------------- To:(越学越不懂) 
你的几个项目中,TreeView中NODE值是动态绑定的吗? --------------------编程问答-------------------- 你的树绑定没有放在 if (!IsPostBack)下面,自然不管你怎么取,服务器端都取不到了 --------------------编程问答-------------------- To:ziyulin0311,如何保存Checked数据是没问题的,问题是前台Check后台读不出来啊。可能是我动态绑定数据的问题 --------------------编程问答-------------------- 当然全部都是动态绑定,赋值,因为是无限分级的权限 --------------------编程问答-------------------- Tview.CheckedNodes 
奇怪,我的TreeView怎么没有这个方法,你是2005还是2003 --------------------编程问答-------------------- TO:(越学越不懂)先说声谢谢!
你说的方法我也试过,最早我也是那样做的。我现在改了一下,重新贴出来,不知是不是思路上的问题,现在选择DropDownList的某个角色后不触发DropDown_SelectedIndexChanged事件,所以俩控件空白
===================================================================================
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using BLL;

public partial class admin_Body_RolerMenu : System.Web.UI.UserControl
{
    protected static string selectValue;//角色选择值
    //protected static bool isSaved,checkOK;//是否保存触发,是否检查过
    RolerMenu rm = new RolerMenu();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //checkOK = false;
            //isSaved = false;
            selectValue = "0";
            ShowPage();
        }
        //this.TVRolerMenu.Attributes.Add("onclick", " ClickTree()");        
    }
    protected void ShowPage()
    {
        ShowRoler();
        ShowRolerMenu();
    }
    protected void ShowRoler()
    {
        rm.BoundRoler("M_Roler", "Select * From M_Roler", DDLRolers, "roler_name", "roler_id");
        DDLRolers.Items.Insert(0,new ListItem("请选择角色","0")); 
    }
    protected void ShowRolerMenu()
    {
        rm.BoundRolerMenu(TVRolerMenu, selectValue);
    }
  
    protected void DDLRolers_SelectedIndexChanged(object sender, EventArgs e)
    {
        selectValue = DDLRolers.SelectedItem.Value.ToString();
        //isSaved = false;
        Label1.Text = "";
        GetCheckNode(TVRolerMenu);
        ShowPage();
    }

    protected void GetCheckNode(TreeView Tview)
    {
        foreach (TreeNode node in Tview.CheckedNodes )
        {
            Label1.Text = node.Text + "|" + Label1.Text;
        }
    }
    protected void BtnSaveRolerMenu_Click(object sender, EventArgs e)
    {
        //isSaved = true;
        GetCheckNode(TVRolerMenu);
        ShowPage();
    }
}
--------------------编程问答-------------------- Vs2005,.net2.0 --------------------编程问答-------------------- UPUP --------------------编程问答-------------------- 给你的第一段代码就是前台Check后台读出来 --------------------编程问答-------------------- :) --------------------编程问答-------------------- To:ziyulin0311(echo)
能帮我看看刚贴的代码上的问题吗:
选择DropDownList的某个角色后不触发DropDown_SelectedIndexChanged事件 --------------------编程问答-------------------- AutoPostBack=true 有没有设置??? --------------------编程问答-------------------- To:ziyulin0311(echo)
设置了。 --------------------编程问答-------------------- DropDownList的AutoPostBack=true 
至于treeview,2005版的有CheckedNodes这个方法了吗,那就更简单,递归都不需要了
无法更改的原因是,如果树的生成没有放在if(!ispostback)下面的话,那么你点sava按钮提交到后台的时候,又会重新生成一遍这个树,那么你做的更改就丢失了 --------------------编程问答-------------------- TO:sleepcraft(越学越不懂),我刚才改过一次代码给你看的,在上面
===================================================================================
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //checkOK = false;
            //isSaved = false;
            selectValue = "0";
            ShowPage();
        }
--------------------编程问答-------------------- ShowRoler();
ShowRolerMenu();
这两个是生成树? --------------------编程问答--------------------
ShowRoler();生成角色,绑定DropDownList:DdlRoler
ShowRolerMenu();根据角色生长权限树,绑定TreeView:TVRolerMenu
RolerMenu rm = new RolerMenu();是业务层 --------------------编程问答-------------------- 我刚才试着增加了一个DropDownlist,把Value和Text预先填好,这可以触发SelectedIndexChanged事件,是代码写的有问题?
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //checkOK = false;
            //isSaved = false;
            selectValue = "0";
            ShowPage();// PostBack后不会执行,但为什么页面为空呢?
        }
        //ShowRoler();//如果在这里梆定角色的DropDownList就可以触发DropDownList,为什么呢?
     }
--------------------编程问答-------------------- 现在这样还是不行吗,应该没什么问题了啊
还有为什么要从dropdownlist的更改去变换权限呢,可以把dropdownlist的项做为你树的根节点,那一个表就可以搞定了 --------------------编程问答-------------------- //ShowRoler();//如果在这里梆定角色的DropDownList就可以触发DropDownList,为什么呢?

==================================
一样的道理,因为dropdownlist的选项变更同样要提交服务器,如果放在!ispostback内,你在选择的时候虽然可以取到你选的内容,但由于没有重新绑定所以丢失了,建议你这么做
while(reader.read())
{
   DdlRoler.items.add(new listitem(text值,value值))//C#用的少,不知道是不是这样写
}
这样等于是在reader循环的时候逐行对dropdownlist添加项,那么不管后面有没有绑定,里面的项始终都在 --------------------编程问答-------------------- sleepcraft(越学越不懂),I'll Try!Thank you very much! --------------------编程问答-------------------- 哦,对了,对于树我也是如此操作的,逐层添加项 --------------------编程问答-------------------- 不客气 --------------------编程问答-------------------- 这次真的要哭了,兄弟再帮我看看啊,逐行对dropdownlist添加项,postback后还是不显示。
=================================================================================
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using BLL;

public partial class admin_Body_RolerMenu : System.Web.UI.UserControl
{
    protected static string selectValue;//角色选择值
    //protected static bool isSaved,checkOK;//是否保存触发,是否检查过
    RolerMenu rm = new RolerMenu();
    protected void Page_Load(object sender, EventArgs e)
    {     
        if (!IsPostBack)
        {
            DAL.DataAccess da = new DAL.DataAccess();
            System.Data.SqlClient.SqlDataReader dataReader = da.RunProcGetReader("select * from M_Roler");
            while (dataReader.Read())
            {
                DDLRolers.Items.Add(new ListItem(dataReader["roler_name"].ToString(), dataReader["roler_id"].ToString()));
            }
            dataReader.Close();
            DDLRolers.DataBind();
            selectValue = "0";
            ShowRolerMenu();
        }  
    }
    private void InitializeComponent()
    {
        this.Load += new System.EventHandler(this.Page_Load);

    }


    protected void ShowPage()
    {
        ShowRoler();
        ShowRolerMenu();
    }
    protected void ShowRoler()
    {
        rm.BoundRoler(DDLRolers);
        DDLRolers.Items.Insert(0,new ListItem("请选择角色","0")); 
    }
    protected void ShowRolerMenu()
    {
        rm.BoundRolerMenu(TVRolerMenu, selectValue);
    }
  
    protected void DDLRolers_SelectedIndexChanged(object sender, EventArgs e)
    {
        selectValue = DDLRolers.SelectedItem.Value.ToString();
        //isSaved = false;
        Label1.Text = "";
        GetCheckNode(TVRolerMenu);
        //ShowPage();
    }

    protected void GetCheckNode(TreeView Tview)
    {
        foreach (TreeNode node in Tview.CheckedNodes )
        {
            Label1.Text = node.Text + "|" + Label1.Text;
        }
    }
    protected void BtnSaveRolerMenu_Click(object sender, EventArgs e)
    {
        //isSaved = true;
        GetCheckNode(TVRolerMenu);
        //ShowPage();
    }
}
--------------------编程问答-------------------- DDLRolers.DataBind();这句不需要了,不是绑定了 --------------------编程问答-------------------- 兄弟,还是一样啊
--------------------编程问答-------------------- 你跟踪一下看看,那里出问题了 --------------------编程问答-------------------- 你把DDLRolers单独拿出来建个页面看看能实现不 --------------------编程问答-------------------- 已确认是用户控件的问题,如果放在单独的页面中就没有这个问题。 --------------------编程问答-------------------- 恩,有可能,我也碰见过用户控件的这种问题 --------------------编程问答-------------------- TO:sleepcraft(越学越不懂)有没有啥解决方案? --------------------编程问答-------------------- 就此结贴!非常感谢sleepcraft(越学越不懂),兄弟你比懂多了。 --------------------编程问答-------------------- 我也碰到了这个问题,还没有解决 --------------------编程问答-------------------- ntForum/ui/scripts/csdn/Plugin/001/face/18.gif][/img]
补充:.NET技术 ,  ASP.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,