Windows 窗体 VB.NET - 使用分层数据填充 TreeView

发布于 2024-08-20 21:42:53 字数 2456 浏览 6 评论 0原文

阿罗哈, 我正在尝试使用 SQL 数据库中的分层数据填充 Windows 窗体应用程序上的树视图。

数据库的结构是:

id_def  id_parent description
1     NULL      Multidificiência
2     NULL      Síndrome
3     NULL      Outros
4     1       Surdez de Transmissão
5     2       Surdez Neurossensorial Ligeira
6     3       Surdez Neurossensorial Média

id_parent 为 NULL 值的记录是主类别,而 id_parent 为 NULL 值的记录是子类别。

任何人都可以帮助编写填充 TreeView 的代码吗? 我设法使用 ASP.NET 应用程序来完成此操作,如果有帮助的话,代码如下:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
        PopulateRootLevel();
}

private void PopulateRootLevel()
{
    SqlConnection objConn = new SqlConnection("Data Source=1.1.1.1;Initial Catalog=DREER_EDUCANDOS2006;User ID=sre_web;Password=xxx");
    SqlCommand objCommand = new SqlCommand("select id_deficiencia,descricao,(select count(*) FROM NecessidadesEspeciais WHERE id_deficiencia_pai=sc.id_deficiencia) childnodecount FROM NecessidadesEspeciais sc where id_deficiencia_pai IS NULL", objConn);
    SqlDataAdapter da = new SqlDataAdapter(objCommand);
    DataTable dt = new DataTable();
    da.Fill(dt);
    PopulateNodes(dt, TreeView1.Nodes);
}

private void PopulateSubLevel(int parentid, TreeNode parentNode)
{
    SqlConnection objConn = new SqlConnection("Data Source=1.1.1.1;Initial Catalog=DREER_EDUCANDOS2006;User ID=sre_web;Password=xxx");
    SqlCommand objCommand = new SqlCommand("select id_deficiencia,descricao,(select count(*) FROM NecessidadesEspeciais WHERE id_deficiencia_pai=sc.id_deficiencia) childnodecount FROM NecessidadesEspeciais sc where id_deficiencia_pai=@id_deficiencia_pai", objConn);
    objCommand.Parameters.Add("@id_deficiencia_pai", SqlDbType.Int).Value = parentid;
    SqlDataAdapter da = new SqlDataAdapter(objCommand);
    DataTable dt = new DataTable();
    da.Fill(dt);
    PopulateNodes(dt, parentNode.ChildNodes);
}


protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
    PopulateSubLevel(Int32.Parse(e.Node.Value), e.Node);
}

private void PopulateNodes(DataTable dt, TreeNodeCollection nodes)
{
    foreach (DataRow dr in dt.Rows)
    {
        TreeNode tn = new TreeNode();
        tn.Text = dr["descricao"].ToString();
        tn.Value = dr["id_deficiencia"].ToString();
        nodes.Add(tn);

        //If node has child nodes, then enable on-demand populating
        tn.PopulateOnDemand = ((int)(dr["childnodecount"]) > 0);
    }
}

Aloha,
I'm trying to populate a treeview on a windows form app with Hierarchical data from a SQL db.

The structure from the database is:

id_def  id_parent description
1     NULL      Multidificiência
2     NULL      Síndrome
3     NULL      Outros
4     1       Surdez de Transmissão
5     2       Surdez Neurossensorial Ligeira
6     3       Surdez Neurossensorial Média

the records with NULL value at id_parent, are the main categories, and the ones with their id_parent, are sub categories.

Can anyone help with the code to populate the TreeView ?
I managed to do it with an ASP.NET app, if it helps, here's the code:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
        PopulateRootLevel();
}

private void PopulateRootLevel()
{
    SqlConnection objConn = new SqlConnection("Data Source=1.1.1.1;Initial Catalog=DREER_EDUCANDOS2006;User ID=sre_web;Password=xxx");
    SqlCommand objCommand = new SqlCommand("select id_deficiencia,descricao,(select count(*) FROM NecessidadesEspeciais WHERE id_deficiencia_pai=sc.id_deficiencia) childnodecount FROM NecessidadesEspeciais sc where id_deficiencia_pai IS NULL", objConn);
    SqlDataAdapter da = new SqlDataAdapter(objCommand);
    DataTable dt = new DataTable();
    da.Fill(dt);
    PopulateNodes(dt, TreeView1.Nodes);
}

private void PopulateSubLevel(int parentid, TreeNode parentNode)
{
    SqlConnection objConn = new SqlConnection("Data Source=1.1.1.1;Initial Catalog=DREER_EDUCANDOS2006;User ID=sre_web;Password=xxx");
    SqlCommand objCommand = new SqlCommand("select id_deficiencia,descricao,(select count(*) FROM NecessidadesEspeciais WHERE id_deficiencia_pai=sc.id_deficiencia) childnodecount FROM NecessidadesEspeciais sc where id_deficiencia_pai=@id_deficiencia_pai", objConn);
    objCommand.Parameters.Add("@id_deficiencia_pai", SqlDbType.Int).Value = parentid;
    SqlDataAdapter da = new SqlDataAdapter(objCommand);
    DataTable dt = new DataTable();
    da.Fill(dt);
    PopulateNodes(dt, parentNode.ChildNodes);
}


protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
    PopulateSubLevel(Int32.Parse(e.Node.Value), e.Node);
}

private void PopulateNodes(DataTable dt, TreeNodeCollection nodes)
{
    foreach (DataRow dr in dt.Rows)
    {
        TreeNode tn = new TreeNode();
        tn.Text = dr["descricao"].ToString();
        tn.Value = dr["id_deficiencia"].ToString();
        nodes.Add(tn);

        //If node has child nodes, then enable on-demand populating
        tn.PopulateOnDemand = ((int)(dr["childnodecount"]) > 0);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城花音 2024-08-27 21:42:53

取一个包含一些分层数据的表:

Id  Name                                ParentNodeId
1   Top-level node 1                    -1
2   A first-level child                  1
3   Another top-level node              -1
4   Another first-level child            1
5   First-level child in another branch  3
6   A second-level child                 2

我重新设计了 另一个示例代码SO 答案,使用上面的表动态填充树视图(假设该表位于 SQL Server 数据库中)。代码示例有点长...

using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;
using System.Data.SqlClient;
public class TreeViewSample : Form
{
    private TreeView _treeView;
    public TreeViewSample()
    {
        this._treeView = new System.Windows.Forms.TreeView();
        this._treeView.Location = new System.Drawing.Point(12, 12);
        this._treeView.Size = new System.Drawing.Size(200, 400);
        this._treeView.AfterExpand +=
            new TreeViewEventHandler(TreeView_AfterExpand);
        this.ClientSize = new System.Drawing.Size(224, 424);
        this.Controls.Add(this._treeView);
        this.Text = "TreeView Lazy Load Sample";
        PopulateChildren(null);
    }

    void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
    {
        if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Tag == "dummy")
        {
            PopulateChildren(e.Node);
        }
    }

    private void PopulateChildren(TreeNode parent)
    {
        // this node has not yet been populated, launch a thread
        // to get the data
        int? parentId = parent != null ? (parent.Tag as DataNode).Id : (int?)null;
        ThreadPool.QueueUserWorkItem(state =>
        {
            IEnumerable<DataNode> childItems = GetNodes(parentId);
            // load the data into the tree view (on the UI thread)
            _treeView.BeginInvoke((MethodInvoker)delegate
            {
                PopulateChildren(parent, childItems);
            });
        });
    }

    private void PopulateChildren(TreeNode parent, IEnumerable<DataNode> childItems)
    {
        TreeNodeCollection nodes = parent != null ? parent.Nodes : _treeView.Nodes;
        TreeNode child;
        TreeNode dummy;
        TreeNode originalDummyItem = parent != null ? parent.Nodes[0] : null;
        foreach (var item in childItems)
        {
            child = new TreeNode(item.Text);
            child.Tag = item;
            dummy = new TreeNode("Loading. Please wait...");
            dummy.Tag = "dummy";
            child.Nodes.Add(dummy);
            nodes.Add(child);
        }
        if (originalDummyItem != null)
        {
            originalDummyItem.Remove();
        }
    }

    private IEnumerable<DataNode> GetNodes(int? parentId)
    {
        List<DataNode> result = new List<DataNode>();
        using (SqlConnection conn = new SqlConnection(@"[your connection string]"))
        using (SqlCommand cmd = new SqlCommand("select * from Nodes where ParentNodeId = @parentNodeId", conn))
        {
            cmd.Parameters.Add(new SqlParameter("@parentNodeId", System.Data.SqlDbType.Int));
            cmd.Parameters["@parentNodeId"].Value = parentId != null ? parentId : -1;
            conn.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                int nodeIdCol = reader.GetOrdinal("NodeId");
                int nameCol = reader.GetOrdinal("Name");
                int parentIdCl = reader.GetOrdinal("ParentNodeId");
                while (reader.Read())
                {
                    result.Add(new DataNode
                       {
                           Id = reader.GetInt32(nodeIdCol),
                           Text = reader.GetString(nameCol),
                           ParentId = reader.IsDBNull(parentIdCl) ? (int?)null : reader.GetInt32(parentIdCl)
                       });
                }
            }
        }
        return result;
    }
}

public class DataNode
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int? ParentId { get; set; }
}

通过使用 Linq-to-SQL 可能可以使数据获取代码变得更漂亮,但我希望代码尽可能完整,所以我决定将其保留下来以保留减少了代码量...(这需要包含一些生成的 Linq-to-SQL 类)。

Take a table with some hierarchical data in it:

Id  Name                                ParentNodeId
1   Top-level node 1                    -1
2   A first-level child                  1
3   Another top-level node              -1
4   Another first-level child            1
5   First-level child in another branch  3
6   A second-level child                 2

I have reworked the sample code from another SO answer, to use the above table to dynamically populate a tree view (assuming the table lives in an SQL server database). The code sample is somewhat lenghty...

using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;
using System.Data.SqlClient;
public class TreeViewSample : Form
{
    private TreeView _treeView;
    public TreeViewSample()
    {
        this._treeView = new System.Windows.Forms.TreeView();
        this._treeView.Location = new System.Drawing.Point(12, 12);
        this._treeView.Size = new System.Drawing.Size(200, 400);
        this._treeView.AfterExpand +=
            new TreeViewEventHandler(TreeView_AfterExpand);
        this.ClientSize = new System.Drawing.Size(224, 424);
        this.Controls.Add(this._treeView);
        this.Text = "TreeView Lazy Load Sample";
        PopulateChildren(null);
    }

    void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
    {
        if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Tag == "dummy")
        {
            PopulateChildren(e.Node);
        }
    }

    private void PopulateChildren(TreeNode parent)
    {
        // this node has not yet been populated, launch a thread
        // to get the data
        int? parentId = parent != null ? (parent.Tag as DataNode).Id : (int?)null;
        ThreadPool.QueueUserWorkItem(state =>
        {
            IEnumerable<DataNode> childItems = GetNodes(parentId);
            // load the data into the tree view (on the UI thread)
            _treeView.BeginInvoke((MethodInvoker)delegate
            {
                PopulateChildren(parent, childItems);
            });
        });
    }

    private void PopulateChildren(TreeNode parent, IEnumerable<DataNode> childItems)
    {
        TreeNodeCollection nodes = parent != null ? parent.Nodes : _treeView.Nodes;
        TreeNode child;
        TreeNode dummy;
        TreeNode originalDummyItem = parent != null ? parent.Nodes[0] : null;
        foreach (var item in childItems)
        {
            child = new TreeNode(item.Text);
            child.Tag = item;
            dummy = new TreeNode("Loading. Please wait...");
            dummy.Tag = "dummy";
            child.Nodes.Add(dummy);
            nodes.Add(child);
        }
        if (originalDummyItem != null)
        {
            originalDummyItem.Remove();
        }
    }

    private IEnumerable<DataNode> GetNodes(int? parentId)
    {
        List<DataNode> result = new List<DataNode>();
        using (SqlConnection conn = new SqlConnection(@"[your connection string]"))
        using (SqlCommand cmd = new SqlCommand("select * from Nodes where ParentNodeId = @parentNodeId", conn))
        {
            cmd.Parameters.Add(new SqlParameter("@parentNodeId", System.Data.SqlDbType.Int));
            cmd.Parameters["@parentNodeId"].Value = parentId != null ? parentId : -1;
            conn.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                int nodeIdCol = reader.GetOrdinal("NodeId");
                int nameCol = reader.GetOrdinal("Name");
                int parentIdCl = reader.GetOrdinal("ParentNodeId");
                while (reader.Read())
                {
                    result.Add(new DataNode
                       {
                           Id = reader.GetInt32(nodeIdCol),
                           Text = reader.GetString(nameCol),
                           ParentId = reader.IsDBNull(parentIdCl) ? (int?)null : reader.GetInt32(parentIdCl)
                       });
                }
            }
        }
        return result;
    }
}

public class DataNode
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int? ParentId { get; set; }
}

The data fetching code can probably be made a bit prettier by using Linq-to-SQL, but I wanted the same to be as complete as possible, so I decided to leave that out to keep the amount of code down... (that would require the inclusion of some generated Linq-to-SQL classes).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文