读书人

小弟我搞了一天了treeview有关问题

发布时间: 2012-06-20 20:37:21 作者: rapoo

我搞了一天了,treeview问题,高手们睡了没有,进来看看!
原来我的数据库中的结构是这样的:
class表:

C_id ParentsId C_class
1 0 软件工程
2 0 网络编程
3 0 C#程序设计
4 1 第一章
5 1 第二章
6 2 第一章
7 2 第二章
8 2 第三章
9 3 第一章
10 3 第二章

用TreeView控件绑定 想使之效果为:第一级节点显示课程的名称 然后他们下面可以展开他们的章节,比如软件工程有 第一章 第二章 ;网络编程有 第一章 第二章 第三章 。上面这样的数据库结构配合下面的程序,可以实现这个效果。
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
string SqlConn=System.Configuration.ConfigurationSettings.AppSettings[ "ConnString "];
Conn=new SqlConnection(SqlConn);
CreateDataSet();
InitTree(this.TreeView1.Nodes, "0 ");
}
private DataSet CreateDataSet()
{
SqlStr= "select * from class ";
da=new SqlDataAdapter(SqlStr,Conn);
data=new DataSet();
da.Fill(data, "tree ");
return data;
}
private void InitTree(TreeNodeCollection Nds,string parentId)
{
TreeNode tmpNd;
DataRow[] rows=data.Tables[0].Select( "ParentId= ' "+parentId+ " ' ");
foreach(DataRow row in rows)
{
tmpNd=new TreeNode();
tmpNd.ID=row[ "C_id "].ToString();
tmpNd.Text=row[ "C_class "].ToString();
tmpNd.NavigateUrl= "index.aspx?class= "+row[ "parentId "].ToString()+ "&C_id= "+row[ "C_id "].ToString();
Nds.Add(tmpNd);
InitTree(tmpNd.Nodes,tmpNd.ID);
}
}
这样做主要思想是,先从表里找出根节点的数据,然后生成TreeNode节点插入到TreeView中,然后用第归寻找当前节点的子节点,生成TreeNode并插入到TreeView中。这样做是可以的。
但我想从新设计一下数据库,让它更容易理解些。我想做成这样:
C_id NodeId C_class
1 第一章 软件工程
2 第二章 软件工程


3 第三章 软件工程
4 第一章 C#程序设计
5 第二章 C#程序设计
6 第三章 C#程序设计
7 第一章 网络编程
8 第二章 网络编程

现在想这样做数据库或者需要再加一些节点(比如ParentId),来达到同样的效果,也就是第一级级节点显示课程名称 然后他们有多少章节 就可以展开看到。
基本就是这样,我想了一天,高手们,帮我指点一下。我现在主要困惑的问题是,怎么样插入课程的章节到它所在的课程名称节点下!

[解决办法]
推荐一篇相关的文章-ASP.NET2.0 中实现 Treeview 与数据库绑定(含代码):
http://www.why100000.com/_articles/show_a_article.asp?autoid=36&tab=tabAspNet
[解决办法]
我确定把此贴顶到高手来为止!

顶你这句
[解决办法]
我对treeview用的比较熟悉,请参观一下效果:
http://www.addtoo.net/Visitor/View.aspx
数据库树形结构我参考的是这篇文章:
http://www.sitepoint.com/article/hierarchical-data-database/2
[解决办法]
学习绑定
[解决办法]
给你一个例子

/// <summary>
/// 生成树
/// </summary>
/// <param name= "iUserID "> 用户ID </param>
/// <param name= "trvMenu "> 菜单Tree </param>
/// <param name= "iMenuID "> 菜单ID </param>
/// <param name= "iMenuRightCount "> 有权限的数目 </param>
public void GenerateTree(int iUserID, TreeView trvMenu, int iMenuID, out int iMenuRightCount)
{
iMenuRightCount = 0;
DataGroup dgAllMenus = this.GetUserMenus(iUserID);

if ( dgAllMenus == null ) //如果查询时出现错误, 只添加退出菜单

{
TreeNode rootNode = new TreeNode();
rootNode.Text = "退出 ";
rootNode.NodeData = " ";
rootNode.Expanded = true;
trvMenu.Nodes.Add(rootNode);

TreeNode nodLoginAgain = new TreeNode();
nodLoginAgain.Text = "重新登录 ";
nodLoginAgain.NodeData = " ";
nodLoginAgain.NavigateUrl = "Login.aspx?Type=LoginAgain ";
rootNode.Nodes.Add(nodLoginAgain);

TreeNode nodQuit = new TreeNode();
nodQuit.Text = " <div onclick= 'window.close(); '> 退出系统 </div> ";
nodQuit.NodeData = " ";
rootNode.Nodes.Add(nodQuit);

return;
}

//获取一级菜单
DataView dvRootMenu = new DataView(dgAllMenus.Table, "MenuLevel = 1 ", "DisplayNo ", DataViewRowState.CurrentRows);

if (dvRootMenu.Count == 0) //没有权限,只显示退出
{
iMenuRightCount = 0;

TreeNode rootNode = new TreeNode();
rootNode.Text = "退出 ";
rootNode.NodeData = " ";


rootNode.Expanded = true;
trvMenu.Nodes.Add(rootNode);

TreeNode nodLoginAgain = new TreeNode();
nodLoginAgain.Text = "重新登录 ";
nodLoginAgain.NodeData = " ";
nodLoginAgain.NavigateUrl = "Login.aspx?Type=LoginAgain ";
rootNode.Nodes.Add(nodLoginAgain);

TreeNode nodQuit = new TreeNode();
nodQuit.Text = " <div onclick= 'window.close(); '> 退出系统 </div> ";
nodQuit.NodeData = " ";
rootNode.Nodes.Add(nodQuit);
}
else //有权限
{
iMenuRightCount = 1;

string[] strMenuIDPath = this.GetMenuIDPath(iMenuID); //Get Menu ID Path
string strNodeIndex = " ";

for (int i=0; i <dvRootMenu.Count; i++)
{
//添加一级菜单
TreeNode firstNode = new TreeNode();
firstNode.Text = dvRootMenu[i][ "MenuName "].ToString();
firstNode.NodeData = dvRootMenu[i][ "MenuID "].ToString();
firstNode.Expanded = true;
trvMenu.Nodes.Add(firstNode);

if (strMenuIDPath[0] != "-1 ")
{
for (int j=0; j <strMenuIDPath.Length; j++)
{
if (strMenuIDPath[j] == firstNode.NodeData)
{
strNodeIndex = i.ToString();
break;
}
}
}

this.CreateNode(Int32.Parse(dvRootMenu[i][ "MenuID "].ToString()), 2, firstNode, dgAllMenus.Table, strMenuIDPath, ref strNodeIndex);
}

TreeNode rootNode = new TreeNode();
rootNode.Text = "退出 ";
rootNode.NodeData = " ";
rootNode.Expanded = true;
trvMenu.Nodes.Add(rootNode);

TreeNode nodLoginAgain = new TreeNode();
nodLoginAgain.Text = "重新登录 ";
nodLoginAgain.NodeData = " ";
nodLoginAgain.NavigateUrl = "Login.aspx?Type=LoginAgain ";
rootNode.Nodes.Add(nodLoginAgain);

TreeNode nodQuit = new TreeNode();
nodQuit.Text = " <div onclick= 'window.close(); '> 退出系统 </div> ";
nodQuit.NodeData = " ";
rootNode.Nodes.Add(nodQuit);

if (strMenuIDPath[0] != "-1 ")
{
try
{
trvMenu.SelectedNodeIndex = strNodeIndex;
}
catch
{
}
}
}
}

/// <summary>
/// 循环生成树的结构
/// </summary>
/// <param name= "fatherID "> 上一级菜单ID </param>
/// <param name= "menuLevel "> 菜单级数 </param>
/// <param name= "parentNode "> 上一级的Node </param>
/// <param name= "dtMenu "> DataTable </param>


/// <param name= "strMenuIDPath "> Menu ID Path </param>
/// <param name= "strNodeIndex "> Node Index </param>
private void CreateNode(int fatherID, int menuLevel, TreeNode parentNode, DataTable dtMenu, string[] strMenuIDPath, ref string strNodeIndex)
{
DataRow[] drMenu = dtMenu.Select( "FatherID = " + fatherID + " AND MenuLevel = " + menuLevel, "DisplayNo ");

int intIndex = 0;
foreach (DataRow dr in drMenu)
{
TreeNode curNode = new TreeNode();
curNode.Text = dr[ "MenuName "].ToString();
curNode.NodeData = dr[ "MenuID "].ToString();

if (dr[ "MenuPath "].ToString() != " ")
{
curNode.NavigateUrl = dr[ "MenuPath "].ToString();
curNode.Target = "MainFrame ";
}

if (strMenuIDPath[0] != "-1 ")
{
for (int i=0; i <strMenuIDPath.Length; i++)
{
if (strMenuIDPath[i] == curNode.NodeData)
{
strNodeIndex += ". " + intIndex.ToString();
curNode.Expanded = true;
break;
}
}
}

parentNode.Nodes.Add(curNode);

//添加下一级的菜单
CreateNode(Int32.Parse(dr[ "MenuID "].ToString()), menuLevel+1, curNode, dtMenu, strMenuIDPath, ref strNodeIndex);

intIndex++;
}
}
[解决办法]
表还是用你第一个表,基本思路——循环生成父节点,递归生成子节点
/// <summary>
/// 绑定父节点
/// </summary>
private void Bindclass()
{
class[] _m = Getclass();//实体类class。(属性说明自动提取数据库字段的描述信息)具体写法后面有
foreach (class _l in _m)
{
// 循环生成根节点
TreeNode n = new TreeNode(_l.mod_name);
n.ToolTip = _l.mod_name;
n.Value = _l.mod_id.ToString();
n.SelectAction = TreeNodeSelectAction.None;
tmpNd.Nodes.Add(n);
CreateNode(n, _l);
}
}

/// <summary>
/// 递归生成所有子节点
/// </summary>
/// <param name= "p_Node "> 节点 </param>
/// <param name= "p_class "> 模块 </param>
private void CreateNode(TreeNode p_Node, class p_class)
{
class[] _m = GetChildclass(p_class);
foreach (class _l in _m)
{
TreeNode n = new TreeNode(_l.mod_name);
n.ToolTip = _l.mod_name;
n.Value = _l.mod_id.ToString();
n.SelectAction = TreeNodeSelectAction.None;
p_Node.ChildNodes.Add(n);
CreateNode(n, _l);
}
}

/// <summary>
/// 获取所有父模块
/// </summary>
/// <returns> </returns>
public class[] Getclass()
{
string SQL = "select C_id from class where (ParentsId = '0 ') ";
return GetclassBySQL(SQL);
}

/// <summary>
/// 获取父模块下的子模块


/// </summary>
/// <param name= "p_class "> 父模块 </param>
/// <returns> </returns>
public class[] GetChildclass(class p_class)
{
if (p_class != null && p_class.C_id.ToString() != string.Empty)
{
string SQL = "select C_id from class where ParentsId = ' " + p_class.C_id + " ' ";
return GetclassBySQL(SQL);
}
return new class[0];
}

/// <summary>
/// 获取模块数组
/// </summary>
/// <param name= "p_SQL "> SQL 语句 </param>
/// <returns> </returns>
private class [] GetclassBySQL(string p_SQL)
{
ArrayList _a = new ArrayList();
DataTable objData = ado.GetDataTable(p_SQL);//此处就是获取一个datatable ,ado是我自己的数据库链接的类库
for (int i = 0; i < objData.Rows.Count; i++)
{
_a.Add(GetclassByID(objData.Rows[i][ "C_id "].ToString()));
}
objData.Dispose();
objData = null;
return (class[])_a.ToArray(typeof(class));
}

/// <summary>
/// 获取一个class对象
/// </summary>
/// <param name= "p_classID "> classID </param>
/// <returns> </returns>
public class GetclassByID(string p_classID)
{
if (p_classID != string.Empty)
{
class m = new class();
string sql = "select * from class where (C_id = ' "+p_classID+ " ') ";
DataTable objData = ado.GetDataTable(sql);//此处同样也是获取一个datatable
if (objData.Rows.Count > 0)
{
m.C_id= int.Parse(objData.Rows[0][ "C_id "].ToString());
m.ParentsId= int.Parse(objData.Rows[0][ "ParentsId "].ToString());
m.C_class = objData.Rows[0][ "C_class "].ToString();
}
objData.Dispose();
objData = null;
return m;
}
else
return (new class());
}

下面是实体类class的写法
/// <summary>
/// 实体类class。(属性说明自动提取数据库字段的描述信息)
/// </summary>
public class class
{
public class()
{ }
private int _C_id;
private int _ParentsId;
private string _C_class;

/// <summary>
///
/// </summary>
public int C_id
{
set { _C_id= value; }
get { return _C_id; }
}
/// <summary>
///
/// </summary>
public int ParentsId
{
set { _ParentsId = value; }
get { return _ParentsId; }
}
/// <summary>
///
/// </summary>
public string C_class
{
set { _C_class = value; }
get { return _C_class; }
}
}

读书人网 >asp.net

热点推荐