none
TreeView设置了PopulateOnDemand = true的话,报错:PopulateOnDemand 在已具有子级的节点上不能设置为 true RRS feed

  • 问题

  • 模拟数据:

            private DataTable Test_Table()
            {
                DataTable dt = new DataTable();
                DataRow dr;
                dt.Columns.Add(new DataColumn("id", typeof(Guid)));//id列 类型guid
                dt.Columns.Add(new DataColumn("parent_id", typeof(Guid)));//父id列 类型guid
                dt.Columns.Add(new DataColumn("name", typeof(string)));//名称列 类型string
                //构造 公司 根节点
                dr = dt.NewRow();
                var node0=dr[0] = Guid.NewGuid();
                dr[1] = DBNull.Value;
                dr[2] = "** 公司";
                dt.Rows.Add(dr);
                //构造 部门 节点
                string[] department = { "A部门", "B部门", "C部门"};
                for (int i = 0; i < department.Length; i++) {
                    dr = dt.NewRow();
                    var node1=dr[0] = Guid.NewGuid();
                    dr[1] = node0;//(部门节点)属于公司根节点
                    dr[2] = department[i];
                    dt.Rows.Add(dr);
                    //构造 班组 节点
                    for (int j = 1; j < 4; j++)
                    {
                        dr = dt.NewRow();
                        dr[0] = Guid.NewGuid();
                        dr[1] = node1;
                        dr[2] = j+"班组";
                        dt.Rows.Add(dr);
                    }
                }
                return dt;
            }

    方法:

            /// <summary>
            /// 绑定TreeView(利用TreeNodeCollection)
            /// </summary>
            /// <param name="tnc">TreeNodeCollection(TreeView的节点集合)</param>
            /// <param name="pid_val">父id的值</param>
            /// <param name="id">数据库 id 字段名</param>
            /// <param name="pid">数据库 父id 字段名</param>
            /// <param name="text">数据库 文本 字段值</param>
            private void Bind_Tv(DataTable dt,TreeNodeCollection tnc, string pid_val, string id, string pid, string text)
            {
                DataView dv = new DataView(dt);//将DataTable存到DataView中,以便于筛选数据
                TreeNode tn;//建立TreeView的节点(TreeNode),以便将取出的数据添加到节点中
                //以下为三元运算符,如果父id为空,则为构建“父id字段 is null”的查询条件,否则构建“父id字段=父id字段值”的查询条件
                string filter = string.IsNullOrEmpty(pid_val) ? pid + " is null" : string.Format(pid + "='{0}'", pid_val);
                dv.RowFilter = filter;//利用DataView将数据进行筛选,选出相同 父id值 的数据
                foreach (DataRowView drv in dv)
                {
                    tn = new TreeNode();//建立一个新节点(学名叫:一个实例)
                    tn.Value = drv[id].ToString();//节点的Value值,一般为数据库的id值
                    tn.Text = drv[text].ToString();//节点的Text,节点的文本显示
                    tn.Expanded = false;
                    tn.PopulateOnDemand = true;
                    tnc.Add(tn);//将该节点加入到TreeNodeCollection(节点集合)中
                    Bind_Tv(dt, tn.ChildNodes, tn.Value, id, pid, text);//递归(反复调用这个方法,直到把数据取完为止)
                }
            }

    page_load调用

                if (!IsPostBack)
                {
                    Bind_Tv(Test_Table(), TreeView1.Nodes, null, "id", "parent_id", "name");
                }
    哪位高人帮下忙。
    2010年4月6日 1:23

答案

  • 你好,

    你的代码中并没有使用到PopulateOnDemand的功能,你的代码功能只是一个简单的数据绑定代码,而PopulateOnDemand支持动态节点填充,则展开该节点后在运行时填充该节点。注意,是运行时。
    若要动态填充节点,必须为 TreeNodePopulate 事件定义填充节点的事件处理方法。

    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Data.SqlClient" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <script runat="server">

      void PopulateNode(Object sender, TreeNodeEventArgs e)
      {

        // Call the appropriate method to populate a node at a particular level.
        switch(e.Node.Depth)
        {
          case 0:
            // Populate the first-level nodes.
            PopulateCategories(e.Node);
            break;
          case 1:
            // Populate the second-level nodes.
            PopulateProducts(e.Node);
            break;
          default:
            // Do nothing.
            break;
        }

      }

      void PopulateCategories(TreeNode node)
      {

        // Query for the product categories. These are the values
        // for the second-level nodes.
        DataSet ResultSet = RunQuery("Select CategoryID, CategoryName From Categories");

        // Create the second-level nodes.
        if(ResultSet.Tables.Count > 0)
        {

          // Iterate through and create a new node for each row in the query results.
          // Notice that the query results are stored in the table of the DataSet.
          foreach (DataRow row in ResultSet.Tables[0].Rows)
          {

            // Create the new node. Notice that the CategoryId is stored in the Value property
            // of the node. This will make querying for items in a specific category easier when
            // the third-level nodes are created.
            TreeNode newNode = new TreeNode();
            newNode.Text = row["CategoryName"].ToString();
            newNode.Value = row["CategoryID"].ToString();       

            // Set the PopulateOnDemand property to true so that the child nodes can be
            // dynamically populated.
            newNode.PopulateOnDemand = true;

            // Set additional properties for the node.
            newNode.SelectAction = TreeNodeSelectAction.Expand;

            // Add the new node to the ChildNodes collection of the parent node.
            node.ChildNodes.Add(newNode);

          }

        }

      }

      void PopulateProducts(TreeNode node)
      {

        // Query for the products of the current category. These are the values
        // for the third-level nodes.
        DataSet ResultSet = RunQuery("Select ProductName From Products Where CategoryID=" + node.Value);

        // Create the third-level nodes.
        if(ResultSet.Tables.Count > 0)
        {

          // Iterate through and create a new node for each row in the query results.
          // Notice that the query results are stored in the table of the DataSet.
          foreach (DataRow row in ResultSet.Tables[0].Rows)
          {

            // Create the new node.
            TreeNode NewNode = new TreeNode(row["ProductName"].ToString());

            // Set the PopulateOnDemand property to false, because these are leaf nodes and
            // do not need to be populated.
            NewNode.PopulateOnDemand = false;

            // Set additional properties for the node.
            NewNode.SelectAction = TreeNodeSelectAction.None;

            // Add the new node to the ChildNodes collection of the parent node.
            node.ChildNodes.Add(NewNode);

          }

        }

      }

      DataSet RunQuery(String QueryString)
      {

        // Declare the connection string. This example uses Microsoft SQL Server
        // and connects to the Northwind sample database.
        String ConnectionString = "server=localhost;database=NorthWind;Integrated Security=SSPI";

        SqlConnection DBConnection = new SqlConnection(ConnectionString);
        SqlDataAdapter DBAdapter;
        DataSet ResultsDataSet = new DataSet();

        try
        {

          // Run the query and create a DataSet.
          DBAdapter = new SqlDataAdapter(QueryString, DBConnection);
          DBAdapter.Fill(ResultsDataSet);

          // Close the database connection.
          DBConnection.Close();

        }
        catch(Exception ex)
        {

          // Close the database connection if it is still open.
          if(DBConnection.State == ConnectionState.Open)
          {
            DBConnection.Close();
          }

          Message.Text = "Unable to connect to the database.";

        }

        return ResultsDataSet;

      }

    </script>

    <html  >
      <head runat="server">
        <title>TreeView PopulateNodesFromClient Example</title>
    </head>
    <body>
        <form id="form1" runat="server">

          <h3>TreeView PopulateNodesFromClient Example</h3>

          <asp:TreeView id="LinksTreeView"
            Font-Names= "Arial"
            ForeColor="Blue"
            EnableClientScript="true"
            PopulateNodesFromClient="true" 
            OnTreeNodePopulate="PopulateNode"
            runat="server">

            <Nodes>

              <asp:TreeNode Text="Inventory"
                SelectAction="Expand" 
                PopulateOnDemand="true"/>

            </Nodes>

          </asp:TreeView>

          <br /><br />

          <asp:Label id="Message" runat="server"/>

        </form>
      </body>
    </html>
    • 已标记为答案 杜宏宇 2010年4月6日 5:21
    2010年4月6日 4:23
    版主