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