无限递归建立TreeView,通过结点传值问题

liefdiy 2009-03-29 10:25:28
要建两个表
----------------------------------------------------------------
Category表结构为:
CategoryID | Desn(category的名称) | ParentID
1 图书 1
2 电子产品 1
3 生活用品 1
----------------------------------------------------------------
Product表结构为:
ProductID Name CategoryID
1 三国演义 1
2 寻秦记 1
3 手机 2
4 MP4 2
5 洗衣粉 3
6 饭碗 3

----------------------------------------------------------------
我想做一个框架集,左边是一个TreeView,页面就叫做left.aspx吧,在框架集中的name="Left"
右边right.aspx是主要内容,在框架集中的name="right"

怎样用递归把Category和Product绑定到TreeView中?如:
图书
|-三国演义
|-寻秦记
电子产品
|-手机
|-MP4
生活用品
|-洗衣粉
|-饭碗

怎样实现当点击【图书】的时候把它的ID传给框架集中的right.aspx?

【小弟我是新手,但是抱着认真、虚心、耐心的态度在学习,希望CSDN伟大的朋友们能给予一些帮助,不胜感激!】

...全文
615 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
huangzqunnxyz 2011-04-28
  • 打赏
  • 举报
回复
正要写一个建立TreeView的程序,学习了!!
liuqf456789 2010-05-04
  • 打赏
  • 举报
回复
好强!!!!!!!!!
liefdiy 2009-04-03
  • 打赏
  • 举报
回复
TO:风语者

你真划得来,白抢了我80分
liefdiy 2009-03-29
  • 打赏
  • 举报
回复
TO:风语者
你提供的代码我有试过,经常在 dataView.RowFilter = "ownerid = " + classParentID + ""; 这个地方报错,说要我检查是否无限递归,那是怎么回事?
zzxap 2009-03-29
  • 打赏
  • 举报
回复
[CODE=C#]
TreeView递归操作 2008-06-02 09:52

分类:Asp.Net
字号: 大 中 小
/// <summary>
/// 显示案卷类型
/// </summary>
private void Display案卷类型()
{
this.lv案卷类型.Items.Clear();
this.tv案卷类型.Nodes[0].Nodes.Clear();

DataTable temp = this.obj案卷类型管理.查看案卷类型代码();

if (temp.Rows.Count > 0)
{
foreach (DataRow objDataRow in temp.Rows)
{
this.lv案卷类型.Items.Add(new LVI案卷类型(objDataRow["记录顺序号"].ToString(),
objDataRow["代码"].ToString(),
objDataRow["内容"].ToString()));
}

this.AddTreeNode("案卷类型", this.tv案卷类型.Nodes[0], temp);
}
}

/// <summary>
/// 添加节点
/// </summary>
private void AddTreeNode(string 父节点名称, TreeNode tn, DataTable objDataTable)
{
DataView objDataView = new DataView(objDataTable);

objDataView.RowFilter = "父节点名称='" + 父节点名称 + "'";

foreach(DataRowView objDRV in objDataView)
{
TreeNode objTreeNode = new TreeNode();

//添加根节点
if (null == tn)
{
objTreeNode.Text = objDRV["内容"].ToString();

this.tv案卷类型.Nodes.Add(objTreeNode);

this.AddTreeNode(objDRV["内容"].ToString(), objTreeNode, objDataTable);
}

else
{
objTreeNode.Text = objDRV["内容"].ToString();

tn.Nodes.Add(objTreeNode);

this.AddTreeNode(objDRV["内容"].ToString(), objTreeNode, objDataTable);
}
}

this.tv案卷类型.ExpandAll();

this.tv案卷类型.SelectedNode = this.tv案卷类型.Nodes[0];
}

/// <summary>
/// 遍历节点
/// </summary>
/// <param name="theTNS">节点</param>
/// <param name="key">关键字</param>
private void SearchTreeNode(TreeNode theTNS, string key)
{
foreach (TreeNode theTN in theTNS.Nodes)
{
if (theTN.Text.Trim().Equals(key))
{
this.tv案卷类型.SelectedNode = theTN;

//this.txt父节点.Text = theTN.Parent.Text;

break;
}

else
{
SearchTreeNode(theTN, key);
}
}
}

/// <summary>
/// 检查子节点
/// </summary>
/// <param name="theTNS">节点</param>
/// <param name="key">关键字</param>
private void CheckChildNode(TreeNode theTNS, string key, ref bool hasChild)
{
foreach (TreeNode theTN in theTNS.Nodes)
{
if (theTN.Text.Trim().Equals(key))
{
if (theTN.Nodes.Count > 0)
{
MessageBox.Show(this, "请先删除该节点的子节点!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);

hasChild = true;

return;
}
}

else
{
CheckChildNode(theTN, key, ref hasChild);
}
}
}



/********************/

/// <summary>
/// 绑定树
/// </summary>
private void BindTreeView()
{
this.rtvTest.Nodes.Clear();

this.AddTreeNode("0", null, this.DataSource);
}

private void AddTreeNode(string parentId, Telerik.Web.UI.RadTreeNode tn, DataTable objDataTable)
{
DataView objDataView = new DataView(objDataTable);

objDataView.RowFilter = "PID='" + parentId + "'";

foreach (DataRowView objDRV in objDataView)
{
Telerik.Web.UI.RadTreeNode objTreeNode = new Telerik.Web.UI.RadTreeNode();

//添加根节点
if (null == tn)
{
objTreeNode.Text = objDRV["Name"].ToString();
objTreeNode.Value = objDRV["ID"].ToString();

this.rtvTest.Nodes.Add(objTreeNode);

this.AddTreeNode(objDRV["ID"].ToString(), objTreeNode, objDataTable);
}

else
{
objTreeNode.Text = objDRV["Name"].ToString();
objTreeNode.Value = objDRV["ID"].ToString();

tn.Nodes.Add(objTreeNode);

this.AddTreeNode(objDRV["ID"].ToString(), objTreeNode, objDataTable);
}
}
}

[/CODE]
zzxap 2009-03-29
  • 打赏
  • 举报
回复
/// <summary>
/// 建立菜单功能树
/// </summary>
/// <param name="myDv">包含菜单表所有记录的视图</param>
/// <param name="TNC">树节点的Collection,传入myTv.Nodes就行了</param>
/// <param name="classParentID">上级菜单ID</param>
public static void CreateMenuTree(DataView myDv, TreeNodeCollection TNC,string classParentID)
{
try
{
DataView dataView = new DataView();
dataView = myDv.Table.Copy().DefaultView ;
dataView.RowFilter = "ownerid = " + classParentID + "";
foreach(DataRowView drv in dataView)
{
if(UserRight.GetIsShow(drv["MenuValue"].ToString(),drv["Right"].ToString(),drv["MenuId"].ToString()))
{
TreeNode tn = new TreeNode();
tn.ID = drv["menuID"].ToString();
tn.Text = "<span onmousemove=javascript:title='" +
drv["menuName"].ToString().Trim() + "'>" + drv["menuName"].ToString().Trim() + "</span>";
tn.ImageUrl = drv["imgurl"].ToString();
tn.NavigateUrl = drv["menuhref"].ToString()==""?"":drv["menuhref"].ToString() + "?menuid=" + drv["menuid"].ToString();
tn.Target = "mainFrame";
TNC.Add(tn);

CreateMenuTree(myDv,tn.Nodes,tn.ID);
}
}
}
catch(Exception ex)
{
Hansheen.EOffice_Ora.Components.Error.Log("获取树错误:" + ex.Message);
}
}

调用实例:
protected Microsoft.Web.UI.WebControls.TreeView tvMenu;
。。。。。
DataView myDv = MenuData.GetMenuData();
MenuData.CreateMenuTree(myDv,tvMenu.Nodes,"0");


private void getAllCheckedNode( Microsoft.Web.UI.WebControls.TreeNodeCollection tnc)
{
node = Microsoft.Web.UI.WebControls.TreeNode
foreach(Microsoft.Web.UI.WebControls.TreeNode node in tnc)
{
if (node.Nodes.Count != 0 )
getAllCheckedNode(node.Nodes);
if (node.Checked )
insertIntoDs(node.Text, node.NodeData);
}
}

zzxap 2009-03-29
  • 打赏
  • 举报
回复
TreeView父子联动效果保持节点状态一致[转]
2007-07-13 11:35
我们大部分都用过TreeView控件,对这个控件的评价也是各式各样的,但是我觉得不论如何它是一个免费的开源的控件,所以我还是在用它。在刚接触ASP.NET的时候,记得需要做一个分配权限的权限树,当时只知道有这个树,经过一天的研究对其服务器端的行为基本以及搞清楚了,但是由于当时的js水平有限,所以对客户端的代码很畏惧,基本没有看过。
当时有这样一个要求:如果一个节点被选中则该节点的所有子节点都要选中,如果该节点的所有子节点取消选择则该节点也要取消选择(节点一致性),相反一样。
还有一个要求就是:如果可以实现三态树则更好(这个有点难,本文中不予讨论)。本文将详细介绍前面要求1。
首先我们要庆幸微软的这个TreeView控件是开源的,不论是客户端代码还是服务器端代码您都可以轻松获得,可以去微软的网站上下载。在网上也见过一些讲述该问题的文章,他们大多是使用一个TreeView之外的js实现,我个人认为从面向对象的观点,该功能属于TreeView,所以没有理由将它分离出去,因此今天我将修改TreeView.htc来实现上面的功能。要想获得该文件(TreeView.htc)可以去微软的网站上下载之。
说实在的该功能曾经也困扰了我很久,一直想解决这个问题,但是一直没有时间来研究TreeView.htc中的代码,今天终于下决心搞定它。
我们知道在TreeView的oncheck中需要激发该事件处理函数,这个函数很容易找到,可以在TreeView生成的客户度脚本中找到,代码片断如下:
oncheck="javascript: if (this.clickedNodeIndex != null) this.queueEvent('oncheck', this.clickedNodeIndex)"
由此我们可以去htc(以后说的htc都指的是TreeView.htc),找到doCheckboxClick方法,只要看名字就知道它是干什么的(命名实在太重要了,否则在3000行代码中找某个函数真的很累)。
该方法是当用户点击CheckBox的使用要处理的函数,函数如下所示:
function doCheckboxClick(el){
var checked = private_getAttribute(el,"checked")
el.checked = !checked;
var evt = createEventObject();
evt.treeNodeIndex = getNodeIndex(el);
g_nodeClicked = el;
_tvevtCheck.fire(evt);
setNodeState(el,el.checked);// maybe need el only,but I think it's safly
}
其中第一行、第二行以及最后一行是我添加的,第一二行是为了在页面回传以后checked属性无效时所做的修改,按照原来的方法在提交后el.checked是undefined,所以导致无法正确同步节点,如果读者有兴趣可以试一试。setNodeState函数,从名字上可以看出该函数是用来设置节点状态的,它将当前你选择的节点作为参数传递到函数内部。如注释中所说实际上你可以只传递el进去,而无需再传一个布尔值,不过我想这样传递可能更安全,不过没有关系,你觉得不爽可以修改:。
下面看看setNodeState的函数体,该函数由两个方法组成,一个是设置所有孩子节点的状态,一个是设置该节点的父节点状态。代码如下:
function setNodeState(el,state){
_setChildNode(el,state);
_setParentNode(el,state);
}
为了可以设置当前节点的所有孩子节点是否和父节点(本节点)状态一至我们需要函数_setChildNode,同理为了使节点的父节点和该节点状态一至我们需要_setParentNode函数。两个函数都是递归函数,将会遍历所有的子节点和所有的父节点以及兄弟节点(为什么要遍历兄弟节点稍候再说),下面我们先看看遍历孩子节点的代码,代码如下所示:
function _setChildNode(el,state){
var childNodes = el.children;
if(childNodes.length > 0){// if has childs
for(var i = 0 ;i<=childNodes.length-1;i++){
private_setAttribute(childNodes[i],"Checked",state);
_saveCheckState(childNodes[i]);
_setChildNode(childNodes[i],state);
}
}
}
该函数先获得当前节点的所有子节点,这里可以直接使用TreeView提供的函数getChildren方法,而我使用的使html的原始方法。如果该节点存在子节点则遍历所有子节点,同时设置子节点的状态和当前节点的状态一致,_saveCheckState函数的作用稍候会介绍。private_setAttribute方法为TreeView提供的一个内部设置属性的方法(js没有private关键字,这里只是做说明而已),该方法将设置每一个节点的Checked属性为当前这个节点的状态。
下面是如何设置父节点状态的代码:
function _setParentNode(el,state){
var parentNode = el.parentElement;
if(parentNode){
if(!_checkSiblingdNode(el)){
private_setAttribute(parentNode,"Checked",state);
_saveCheckState(parentNode);
_setParentNode(parentNode,state);
}
}
}
该函数先获得其父节点,如果父节点存在则检查当前节点的兄弟节点,上面有提到了需要检查兄弟节点,这里检查兄弟节点的目的是:父节点的状态不是由当前节点一个节点控制的(这种情况只存在于当前节点没有兄弟节点的情况下),如果有其他兄弟是选中的,那么父节点是不能被取消了,这样将导致兄弟节点和父子节点不一致不一致。该函数里面也调用了_saveCheckState函数,在后面将介绍之。
下面的代码描述了如何检查兄弟节点的状态,代码如下:
function _checkSiblingdNode(el){
var parentNode = el.parentElement;// you can use getParentTreeNode function in this htc,but I like this usage.
for(var i = 0;i<=parentNode.children.length-1;i++){
if(el != parentNode.children[i]){
if(private_getAttribute(parentNode.children[i],"Checked")){
return true;
}
}
}
return false;
}
正如注释所述,你可以使用getParentTreeNode方法来获得节点的父节点,但是我比较喜欢使用原始的方法:。这里将排除自己(if(el!=parentNode.children[i]))。
有了上面的代码我们就可以做到客户端无刷新的父子节点一致的选择,那么我们现在来介绍一下_saveCheckState函数,如果没有该函数页面提交以后,刚才除了手工点击的节点以外其他的节点都不能保存状态。所以该函数的作用就是要保存所有节点的状态(主要是自动选择的节点),保证在回传之后树的状态依然存在。下面的代码描述了_saveCheckState函数,代码如下:
function _saveCheckState(el){
if(getNodeIndex(el))
queueEvent('oncheck', getNodeIndex(el));
}
该方法首先检查当前节点的index是否有效,如果有效则保存状态。这里需要说一下queueEvent方法做了什么,代码我就不帖了,该函数的实际意义是将客户端的操作保存在一个名为__TreeView1_State__的隐藏域中,这样在回传的时候服务器端会根据该隐藏域,初始化树的状态。其中TreeView1是我在测试系统中TreeView的名字。
最后的问题就是部署的问题了,因为修改了htc,所以在部署的时候需要替换原来的htc文件。
如果有需要修改之后的TreeView.htc(格式化之后的),可以在CSDN上改我留言留下email。我的CSDN帐号是cuike519。
希望微软可以早日将这个功能添加到TreeView控件中,最好也能实现多态的树结构。请浏览blog的相关评论,我会在评论中更新文章!
zzxap 2009-03-29
  • 打赏
  • 举报
回复
public TreeNode fillnode(TreeNode tn)//递归
{
SqlConnection con = DB.creation();
con.Open();

SqlDataAdapter sda = new SqlDataAdapter("select LID,RID from huiyuan where HyID='" + tn.Text + "'", con);
DataSet ds = new DataSet();
sda.Fill(ds);
con.Close();
if (ds.Tables[0].Rows.Count>0)
{
if (!Convert.IsDBNull(ds.Tables[0].Rows[0]["lid"]))
{
TreeNode tnl = new TreeNode();

tnl.Text = ds.Tables[0].Rows[0]["lid"].ToString();
tnl = fillnode(tnl);
tn.ChildNodes.Add(tnl);
}
if (!Convert.IsDBNull(ds.Tables[0].Rows[0]["rid"]))
{
TreeNode tnr = new TreeNode();
tnr.Text = ds.Tables[0].Rows[0]["rid"].ToString();
tnr = fillnode(tnr);
tn.ChildNodes.Add(tnr);
}
}
return tn;

}
zzxap 2009-03-29
  • 打赏
  • 举报
回复
[code=C#]

表结构如下:mytable

_________________________________________________________________________
OrgID/单位ID OrgName/单位名称 UpperOrgID/上级单位ID
A001 省教育厅 0 -----表示是顶级单位
A002 XX大学 A001
A003 XX大学理学院 A002
A004 YY大学 A001

_________________________________________________________________________


想实现的TreeView如下:

-省教育厅
-XX大学
--XX大学理学院
-YY大学
--XX大学理学院

具体有几级节点不能确定,有几级就列出几级来, 查询条件只有一个OrgID,如何实现此树节点?

***************************************************************************************************************************

思路一:

private void CreateTree()
{
string sqltxt = "Persist Security Info=False;User ID=sa;Initial Catalog=zhongtian;Data Source=ytf;Password=xu;";
SqlConnection sqlcon = new SqlConnection(sqltxt);

SqlCommand sqlcom = new SqlCommand("Select * from product_class where fatherid='0'", sqlcon);
try
{
sqlcon.Open();
SqlDataReader sqlreader = sqlcom.ExecuteReader();
while (sqlreader.Read())
{
TreeNode mynode = new TreeNode();
mynode.Text = sqlreader.GetString(2);
mynode.Tag = sqlreader.GetValue(1).ToString() + '|' + sqlreader.GetValue(2).ToString() + '|' + sqlreader.GetValue(3).ToString() + '|' + sqlreader.GetValue(0).ToString();
treeView1.Nodes.Add(mynode);

NextTree(sqlreader.GetValue(0).ToString(), treeView1.Nodes[0]);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
sqlcon.Close();
}
}

private void NextTree(string nodeid, TreeNode parentnode)
{
string sqltxt = "Persist Security Info=False;User ID=sa;Initial Catalog=zhongtian;Data Source=ytf;Password=xu;";
SqlConnection sqlcon = new SqlConnection(sqltxt);

SqlCommand sqlcom = new SqlCommand("Select * from product_class where fatherid='" + nodeid + "'", sqlcon);
try
{
sqlcon.Open();
SqlDataReader sqlreader = sqlcom.ExecuteReader();

while (sqlreader.Read())
{
TreeNode mynode = new TreeNode(sqlreader.GetString(2));
parentnode.Nodes.Add(mynode);
mynode.Tag = sqlreader.GetValue(1).ToString() + '|' + sqlreader.GetValue(2).ToString() + '|' + sqlreader.GetValue(3).ToString() + '|' + sqlreader.GetValue(0).ToString();
NextTree(sqlreader.GetValue(0).ToString(), mynode);

}

}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
sqlcon.Close();
}

}

**********************************************************************************************************************************

思路二:


public void LdlWinBulidTreeView(TreeView treeView,DataTable tb,string strSort,int intKey,int intText)
{
this.treeView=treeView;
this.tb=tb;
this.strSort=strSort;
this.intKey=intKey;
this.intText=intText;
}

public void BulidTopTree()
{
Cursor.Current = new Cursor("L_WAIT01.cur");
treeView.BeginUpdate();

TreeNodeCollection tnParentNodes = treeView.Nodes;
TreeNode tnChildNode;
string strRowFilter;

tnParentNodes.Clear();
DataView dvTop = new DataView();
dvTop.Table = tb;
dvTop.RowFilter = "nItemPK=nParentItemPK";
dvTop.Sort = strSort;
for (int i = 0; i < dvTop.Count; i++)
{
tnChildNode = new TreeNode();
tnChildNode.Tag = dvTop[i][intKey].ToString();
tnChildNode.Text = dvTop[i][intText].ToString();
tnParentNodes.Add(tnChildNode);
strRowFilter = "nItemPK <>nParentItemPK and nParentItemPK=" + dvTop[i][intKey].ToString();
BulidSubTree(tnChildNode, strRowFilter);


Cursor.Current = Cursors.Default;
treeView.EndUpdate();
treeView.TopNode.Expand();

}
}


private void BulidSubTree(TreeNode tnParentNode, string strRowFilter)
{

TreeNode tnChildNode;
string strSubRowFilter;
DataView dvSub = new DataView();
dvSub.Table = tb;
dvSub.RowFilter = strRowFilter;
dvSub.Sort = strSort;
for (int i = 0; i < dvSub.Count; i++)
{
tnChildNode = new TreeNode();
tnChildNode.Tag = dvSub[i][intKey].ToString();
tnChildNode.Text = dvSub[i][intText].ToString();
tnParentNode.Nodes.Add(tnChildNode);
strSubRowFilter = "nItemPK <>nParentItemPK and nParentItemPK=" + tnChildNode.Tag.ToString();
BulidSubTree(tnChildNode, strSubRowFilter);
}
}

[/CODE]
zzxap 2009-03-29
  • 打赏
  • 举报
回复
aspx页面

<asp:TreeView ID="tv" runat="server" ImageSet="Arrows" LineImagesFolder="~/TreeLineImages" OnSelectedNodeChanged="tv_SelectedNodeChanged" OnTreeNodeCheckChanged="tv_TreeNodeCheckChanged" OnTreeNodeCollapsed="tv_TreeNodeCollapsed" OnTreeNodeDataBound="tv_TreeNodeDataBound" OnTreeNodeExpanded="tv_TreeNodeExpanded" OnTreeNodePopulate="tv_TreeNodePopulate">
<ParentNodeStyle Font-Bold="False" />
<HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" />
<SelectedNodeStyle Font-Underline="True" ForeColor="#5555DD" HorizontalPadding="0px"
VerticalPadding="0px" />
<NodeStyle Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" HorizontalPadding="5px"
NodeSpacing="0px" VerticalPadding="0px" />
</asp:TreeView>
生成树的递归方法

public void RecursionUser(string strUserID, TreeNodeCollection NodeParent)
{
DataView dv = new DataView(myDataSet.Tables[0]);
dv.Sort = "LEVEL_CODE";
dv.RowFilter = "PUSER_ID='" + strUserID + "'";

TreeNode tempNode;
for (int i = 0; i < dv.Count; i++)
{
tempNode = new TreeNode();
tempNode.Text = dv[i]["ACCOUNT"].ToString();//要显示的值
tempNode.Value = dv[i]["USER_ID"].ToString();//Node的值
tempNode.Selected = false;
tempNode.Checked = true;//这个是当有checkbox时设置
tempNode.Collapse();

// NodeParent.ChildNodes.Add(tempNode);
NodeParent.Add(tempNode);

RecursionUser(dv[i]["USER_ID"].ToString(), tempNode.ChildNodes);

}


}
调用递归方法 生成树
RecursionUser(NULL_GUID, tv.Nodes);
liefdiy 2009-03-29
  • 打赏
  • 举报
回复
希望各位能给出代码。谢谢了!

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧