PS: 正在找一些分级显示的东西,后来决定用treeview做,事实上也不知道用其他方法如何实现该功能.当然,目的是为了达到文章分级显示,并对级别进行CUID操作,网上找了很久最终找到了这个.起码是可以实现的,不过似乎还是用到了递归,如果以后有好的会继续更新.
本文中的treeview控件id为trvMain,其他地方一般能看懂,不做过多说明
转自:http://hi.baidu.com/51zt/blog/item/d8bffe19c28a527adbb4bde5.html
原文如下:
这几天帮朋友研究一个电子商务网站,遇到一个物品分类的问题,就是想用TREEVIEW控件来做一个无限分级的分类树,现在终于解决了.
解决方法是这样的,查看TreeView控件的属性,会发现其中有一项是"PopulatNodesFromClient"
意思为:是否尝试从客户端填充节点.
那么看到了解释之后,当然是选择值为:"True".
在给"PopulatNodesFromClient"赋值为"True"之后,在TreeView的属性事件中就有一项为TreeNodePopulate事件,为:正在填充TreeNode时激发某事件,那么在给该事件写方法时,就可以写从数据库中读取相应的子节点内容了.
所以,每当TreeNode增加一个节点时,便激发该事件,以填充其子节点.
可生成一个空方法如下:
protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
//
}
下面举个完整的例子(连接数据库的类就不写了,只写了 Default.aspx 内的代码):
效果参考下图:
using System.Data;
using System.Configuration;
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 System.Data.OleDb; public partial class _Default : System.Web.UI.Page
... {
protected void Page_Load(object sender, EventArgs e)
...{
if (!Page.IsPostBack)
...{
InitRoot(trvMain);
}
}
/**//// <summary>
/// 通过SQL语句参数生成需要的DS
/// </summary>
/// <param name="sqlstr">SQL语句</param>
/// <returns></returns>
private DataSet CreateDataSet(string sqlstr)
...{
try
...{
clsConn myConn = new clsConn();
myConn.Open();
OleDbDataAdapter cd = new OleDbDataAdapter();
cd.SelectCommand = new OleDbCommand(sqlstr, myConn.ChangeType());
cd.SelectCommand.CommandType = CommandType.Text;
DataSet dsTree = new DataSet();
cd.Fill(dsTree, "Table");
myConn.Close();
return dsTree;
}
catch
...{
Console.WriteLine("Exception in Main :");
return null;
}
}
/**//// <summary>
/// 插入根结点
/// </summary>
/// <param name="Nds">TREEVIEW控件ID</param>
private void InitRoot(TreeView Nds)
...{
try
...{
DataView dvTree = new DataView();
TreeNode tmpNd;
//调用生成数据集的DS
DataSet ds = CreateDataSet("select * from TYPE where PID=0");
//把ds的数据填充到dvTree中
dvTree.Table = ds.Tables["Table"];
foreach (DataRowView drvTree in dvTree)
...{
//创建要添加结点
tmpNd = new TreeNode();
tmpNd.Value = drvTree["TID"].ToString();
tmpNd.Text = drvTree["TNAME"].ToString();
//给控件添加根结点
Nds.Nodes.Add(tmpNd);
//设置其自动检查是否有子结点
tmpNd.PopulateOnDemand = true;
tmpNd.SelectAction = TreeNodeSelectAction.Expand;
}
}
catch
...{
//
}
}
/**//// <summary>
/// 添加子结点
/// </summary>
/// <param name="tnd">当前添加的结点</param>
private void AddChild(TreeNode tnd)
...{
try
...{
DataView dvTree = new DataView();
TreeNode tmpNd;
//调用生成数据集的DS
DataSet ds = CreateDataSet("select * from TYPE");
//把ds的数据填充到dvTree中
dvTree.Table = ds.Tables["Table"];
//筛选出当前结点的父结点ID
dvTree.RowFilter = "PID=" + tnd.Value.ToString() + "";
foreach (DataRowView drvTree in dvTree)
...{
//创建要添加结点
tmpNd = new TreeNode();
tmpNd.Value = drvTree["TID"].ToString();
tmpNd.Text = drvTree["TNAME"].ToString();
//添加到当前结点处
tnd.ChildNodes.Add(tmpNd);
//设置其自动搜索是否有子结点
tmpNd.PopulateOnDemand = true;
}
if (tnd.ChildNodes.Count != 0)
tnd.SelectAction = TreeNodeSelectAction.Expand;
}
catch
...{
//
}
}
/**//// <summary>
/// 自动填充结点
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void trvMain_TreeNodePopulate(object sender, TreeNodeEventArgs e)
...{
//给目前结点添加子结点
AddChild(e.Node);
}
protected void btnAddChild_Click(object sender, EventArgs e)
...{
try
...{
clsConn myConn = new clsConn();
myConn.Open();
OleDbDataAdapter cd = new OleDbDataAdapter();
string sqlstr = "insert into TYPE (TNAME,PID) VALUES('" + txtChildName.Text.Trim() + "'," + ddlMain.SelectedValue.ToString() + ")";
cd.SelectCommand = new OleDbCommand(sqlstr, myConn.ChangeType());
cd.SelectCommand.ExecuteNonQuery();
ReSet();
ddlMain.DataBind();
}
catch
...{
//
}
}
/**//// <summary>
/// 刷新TREEVIEW
/// </summary>
private void ReSet()
...{
trvMain.Nodes.Clear();
InitRoot(trvMain);
trvMain.ExpandAll();
}
protected void btnReSet_Click(object sender, EventArgs e)
...{
ReSet();
}
}