--------专业
CREATE TABLE [dbo].[series] (
[SID] [int] IDENTITY (100, 1) NOT NULL PRIMARY KEY,
[SNumber] [varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SDisable] [bit] NOT NULL
)
---------项目CREATE TABLE [dbo].[groups] (
[GID] [int] IDENTITY (100, 1) NOT NULL PRIMARY KEY ,
[GNumber] [varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[GName] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[GDisable] [bit] NOT NULL ,
[SID] [int] NOT NULL REFERENCES [dbo].[series] ON DELETE CASCADE
) ON [PRIMARY]
GO------科目CREATE TABLE [dbo].[subject] (
[SID] [int] IDENTITY (100, 1) NOT NULL PRIMARY KEY ,
[SNumber] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SPassLine] [float] NOT NULL ,
[SSumMarks] [float] NOT NULL,
[SDisable] [bit] NOT NULL ,
[GID] [int] NOT NULL REFERENCES [dbo].[groups] ON DELETE CASCADE
) ON [PRIMARY]
GO-------章,节CREATE TABLE [dbo].[chapter] (
[CID] [int] IDENTITY (100, 1) NOT NULL PRIMARY KEY,
[CNumber] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[CName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[CInterID] [int] NULL ,
[FDisable] [bit] NOT NULL ,
[SID] [int] NOT NULL REFERENCES [dbo].[subject] ON DELETE CASCADE
) ON [PRIMARY]
GO
共有 4个表 下面一个表都是 应用上面一个表的主键..
最后一个表 比较特殊 除了引用上面表的主键外..还引用自己的主键,,其实是 2个表合成的..要求: 窗体显示的时候 只能 看到专业
点击专业 + 号 显示项目 ,,一次类推 以上解决 有分 :
另外:; 点击子节点 有事件 ...
右键点击 出现菜单 (添加 修改 删除...)仍然有分 :
楼主你这样的表结构,不适合用递归.用嵌套循环应该就能搞定://循环1,读专业
for(......)
{
//循环2,读某一专业下的所有科目
for(......)
{
.....
}}
//将数据填充到dataTable
DataTable mytable = new DataTable();
//构建表结构
DataRow myRow;
DataColumn Id = new DataColumn("Id", typeof(System.Int32));
mytable.Columns.Add(Id);
DataColumn Name = new DataColumn("Name", typeof(System.String));
mytable.Columns.Add(Name);
DataColumn ParentId = new DataColumn("ParentId", typeof(System.Int32));
mytable.Columns.Add(ParentId);
DataColumn SiteInfo = new DataColumn("SiteInfo", typeof(SiteInfo));
mytable.Columns.Add(SiteInfo);
//填充数据
//注意i是从1开始的,因为数据库收条没有意义,数据库首条记录id为0,会引起死循环
for (int i = 1; i <= cata.Length - 1; i++)
{
myRow = mytable.NewRow();
myRow["Id"] = cata[i].Id;
myRow["Name"] = cata[i].Name;
myRow["ParentId"] = cata[i].ParentId;
myRow["SiteInfo"] = cata[i].SiteInfo; mytable.Rows.Add(myRow);
}
this.InitTree(newNode.ChildNodes, 0, mytable);
//Hashtable ht = new Hashtable(); //for (int i = 1; i < cata.Length; i++)
//{
// ht.Add(cata[i].Id, cata[i]);
//}
//Hashtable allTreeNodes = new Hashtable();
//Hashtable parentNodes = new Hashtable();
////遍历树节点描述并拟向生成树结构
//foreach (DictionaryEntry dict in ht)
//{
// CatalogInfo treeobj = (CatalogInfo)dict.Value;
// if (allTreeNodes.Contains(treeobj.Id))
// continue;
// TreeNode tn = new TreeNode();
// tn.Text = treeobj.Name;
// tn.Value = treeobj.Id.ToString();
// tn.NavigateUrl = "main_right.aspx?catalogid=" + tn.Value;
// tn.Target = "WorkArea";
// generateParentTreeFromNode(tn, (CatalogInfo)treeobj, ht, parentNodes, allTreeNodes);
//} ////将所有根节点放到treeview上
//foreach (DictionaryEntry dict in parentNodes)
//{
// newNode.ChildNodes.Add((TreeNode)dict.Value);
//}
}
}
private void InitTree(TreeNodeCollection Nds, int parentID, DataTable dt)//递归初始化树
{
TreeNode tmpNd;
//递归寻找子节点
DataRow[] rows = dt.Select("ParentID=" + parentID);
foreach (DataRow row in rows)
{
tmpNd = new TreeNode();
tmpNd.Value = row["Id"].ToString();
tmpNd.Text = row["Name"].ToString();
tmpNd.NavigateUrl = "main_right.aspx?catalogid=" + row["Id"].ToString() + "&catalogName=" +Server.UrlEncode(row["Name"].ToString());
tmpNd.Target = "WorkArea";
Nds.Add(tmpNd); InitTree(tmpNd.ChildNodes, Convert.ToInt32(tmpNd.Value), dt);
}
}
/// <summary>
/// 反向树生成算法
/// </summary>
/// <param name="subtr">子节点</param>
/// <param name="subto">子节点描述对象</param>
/// <param name="hashedTreeObject">被保存到哈希表中的子节点描述</param>
/// <param name="hashedParents">被保存到哈希表中的父节点描述</param>
/// <param name="allTreeNodes">被保存到哈希表中的所有节点描述</param>
private void generateParentTreeFromNode(TreeNode subtr, CatalogInfo subto, Hashtable hashedTreeObject, Hashtable hashedParents, Hashtable allTreeNodes)
{ TreeNode trParent;
if (null == hashedTreeObject)
return;
//确定父结点是否存在
if (!hashedTreeObject.Contains(subto.ParentId) || subto.ParentId == subto.Id )
{
//不存在则将当前节点作为根
if (hashedParents == null)
hashedParents = new Hashtable();
if (!hashedParents.Contains(subto.ParentId))
{
hashedParents.Add(subto.Id, subtr);
if (!allTreeNodes.Contains(subto.Id))
allTreeNodes.Add(subto.Id, subtr);
trParent = subtr;
}
}
else
{
//若存在,则获取父结点
CatalogInfo to = (CatalogInfo)hashedTreeObject[subto.ParentId];
//判断父结点是否已经被保存到树节点的哈希表中
if (allTreeNodes.Contains(subto.ParentId))
{
//if (allTreeNodes.Contains(subto.Id))
// return;
trParent = (TreeNode)allTreeNodes[subto.ParentId];
trParent.ChildNodes.Add(subtr);
}
else
{
//父结点不存在于哈希表中,创建父结点并存放到叶子哈希表中
trParent = new TreeNode();
trParent.Text = to.Name;
trParent.Value = to.Id.ToString();
allTreeNodes.Add(subto.ParentId, trParent);
trParent.ChildNodes.Add(subtr);
//递归向上查找
generateParentTreeFromNode(trParent, to, hashedTreeObject, hashedParents, allTreeNodes);
if (!allTreeNodes.Contains(subto.Id))
allTreeNodes.Add(subto.Id, subtr);
} }
}
很簡單的問題,當前顯示的下一層加個臨時節點,隻有在Tv_BeforeExpand事件時才讀取下一層數據这是大致思路...,还有右键菜单的问题,当点击到treeview控件时判断是左键还是右键,如果是右键的话.弹出菜单,事先准备好的,单击事件 用选定的节点的某些参数修改数据库.
private void tvShow_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeNode tn = tvShow.GetNodeAt(e.X, e.Y);
if (tn != null)
{
tvShow.SelectedNode = tn;
}
}
}
{
tvShow.Nodes.Clear();
DataView dv = Bind("select *from series").Tables[0].DefaultView;
ds1 = Bind("select * from groups");
ds2 = Bind("select *from subject");
if (dv.Table.Rows.Count > 0)
{
foreach (DataRowView dr in dv)
{
TreeNode tn = new TreeNode();
tn.Text = dr[2].ToString();
tn.Tag = dr[0].ToString();
tvShow.Nodes.Add(tn);
childnode_1(tn);
}
}
} protected void childnode_1(TreeNode tn)
{
int second =Int32.Parse( tn.Tag.ToString());
DataView dv = ds1.Tables[0].DefaultView;
if (dv.Table.Rows.Count > 0)
{
dv.RowFilter = "SID=" + second;
if (dv.Count > 0)
{
foreach (DataRowView dr in dv)
{
TreeNode tn_2 = new TreeNode();
tn_2.Text = dr[2].ToString();
tn_2.Tag = dr[0].ToString();
tn.Nodes.Add(tn_2);
childnode_2(tn_2);
}
}
}
}
// 依次 类推...............
private void InitTree(DataTable dt,Nodes Nds,string parentId)
{
DataView dv=new DataView(dt);
Node tmpNd;
dv.RowFilter = "parent_id=" + "'" + parentId + "'";
foreach(DataRowView drv in dv)
{
tmpNd=new Node();
tmpNd.DataKey=drv["id"].ToString();
tmpNd.Text=drv["menu_name"].ToString();
if (parentId != "-1")
{
tmpNd.TargetUrl = drv["URL"].ToString();
tmpNd.TargetFrame="main";
tmpNd.ImageUrl = "pic/small0.gif";
}
else
{
tmpNd.ImageUrl = "pic/shequ_man.gif";
}
Nds.Add(tmpNd);
InitTree(dt,tmpNd.Nodes,drv["id"].ToString());
}
}
调用如:
ds = fac.GetMenuListDetail(Request.Cookies["uname"].Value.ToString());
InitTree(ds.Tables[0],trees.Nodes,"-1");