这几天帮朋友研究一个电子商务网站,遇到一个物品分类的问题,就是想用TREEVIEW控件来做一个无限分级的分类树,现在终于解决了.

解决方法是这样的,查看TreeView控件的属性,会发现其中有一项是"PopulatNodesFromClient"

意思为:是否尝试从客户端填充节点.

那么看到了解释之后,当然是选择值为:"True".
在给"PopulatNodesFromClient"赋值为"True"之后,在TreeView的属性事件中就有一项为TreeNodePopulate事件,为:正在填充TreeNode时激发某事件,那么在给该事件写方法时,就可以写从数据库中读取相应的子节点内容了.
所以,每当TreeNode增加一个节点时,便激发该事件,以填充其子节点.

可生成一个空方法如下:
    protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
    {
            //
    }

下面举个完整的例子(连接数据库的类就不写了,只写了 Default.aspx  内的代码):

效果参考下图:

代码如下:

using System;
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();
    }
}