none
关于treeview的BeforeExpand事件的用法,提高节点展开的效率,请老师指点 RRS feed

  • 问题

  • 代码编译是通过了,但是就是从数据库提出来的数据显示不了,一旦超过连接的时间,就会报出异常,我将代码贴如下,请指点:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;

    namespace WindowsFormsApplication17
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                TreeView tv = new TreeView();
                tv.AfterSelect += new TreeViewEventHandler(tv_AfterSelect);
                tv.Dock = DockStyle.Fill;
                this.BuildTree(tv.Nodes, 0);
                this.Controls.Add(tv);
            }

            private void tv_AfterSelect(object sender, TreeViewEventArgs e)
            {
                // 选择节点后,获取当前节点的信息
                // 你可以将下列信息赋给你对应的控件
                DataRow row = (DataRow)e.Node.Tag;

                Int32 FInterID = (Int32)row["FInterID"];
                Int32 ParentId = (Int32)row["FParentID"];
                String FName = (String)row["FName"];
            }

            private DataTable fSampleDataSource;
            public DataTable SampleDataSource
            {
                get  //这一段是我连接本人数据的代码
                {
                    SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
                    SqlCommand cmd = thisconnection.CreateCommand();
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP";
                    SqlDataAdapter adapter = new SqlDataAdapter();
                    adapter.SelectCommand = cmd;
                    DataSet ds = new DataSet();
                    adapter.Fill(ds, "ICBOMGROUP");
                    this.fSampleDataSource = ds.Tables[0];
                    return fSampleDataSource;
                }
            }

            /// <summary>
            /// 创建目录和文件树
            /// </summary>
            /// <param name="fNodes"></param>
            /// <param name="fPath"></param>
            public void BuildTree(TreeNodeCollection fNodes, Int32 fParentId)
            {
                foreach (DataRow row
                    in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
                {
                    TreeNode node = new TreeNode();
                    node.Text = row["FName"].ToString();
                    node.Tag = row;
                    // 递归创建子节点
                    this.BuildTree(node.Nodes, (Int32)row["FInterID"]);
                    fNodes.Add(node);
                }
            }

            private void Form1_Load(object sender, EventArgs e)
            {

            }
        }
    }


    另外我将数据库中的表结构贴出来如下:
    表名:ICBOMGROUP

    FInterID(BOM内码)    FParentID(父BOM内码)  FName(名称)       FNumber(产品代码)
    1039                               0                            产品                        0
    2296                               0                            喷印机壳                  1
    6497                               0                            丝印彩盒                  2
    7035                               0                            外发加工                  3
    1041                               1039                       VGA电视盒              01
    1071                               1041                       TV3488B系列          01.01
    1140                               1071                       TV2188EBOM          01.01.01
    1144                               1140                       普通订单                 01.01.01.01
    1146                               1144                       TV2188E 中文BOM   01.01.01.01.01
    1145                               1140                       特殊订单                 01.01.01.02
    1129                               1039                       XGA电视盒              02
    1199                               1129                       TV5811T系列           02.02
    1212                               1199                       TV5811BOM            02.02.01
    2297                               2296                       机壳-上盖                1.01
    2308                               2297                       GM998                    1.01.01
    2312                               2308                       GM998上盖 灰色      1.01.01.01
    7039                               7035                       支架组件                  3.01
    7040                               7039                       PD1048                   3.01.01
    7172                               7040                       PD1048支架组件       3.01.01.01


    在C#FORM界面中,要求有一个treeview控件,根据表结构,生成根结点和子结点:
    比如说FParentID为0,为一阶,再根据父节点和子节点依次生成下面的结点,例:
    0(产品)
       01(VGA电视盒)
         01.01(TV3488B系列)
            01.01.01(TV2188E BOM)
                01.01.01.01(普通订单)
                01.01.01.02(特殊订单)
    省略了

    请老师指点,如何在快速生成只有父节点为0的树状信息,当单击一父节点时才会弹出下一子节点的信息,现在连编译都无法通过,连接数据库超时,该如何修改,这个问题困扰了很久了

    2009年10月9日 7:18

答案

  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Data.SqlClient;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private String LoadingKey = "57868058-716C-4D36-B48E-D840AA2C50C3";
            private TreeView treeView1;
    
            public Form1()
            {
                InitializeComponent();
    
                this.BuildTreeView();
            }
    
            private void BuildTreeView()
            {
                if (this.treeView1 == null)
                {
                    this.treeView1 = new TreeView();
                    this.treeView1.Dock = DockStyle.Fill;
                    this.Controls.Add(this.treeView1);
                    this.treeView1.BeforeExpand += new TreeViewCancelEventHandler(treeView1_BeforeExpand);
                }
    
                this.treeView1.BeginUpdate();
                this.BuildTreeView(this.treeView1.Nodes, 0);
                this.treeView1.EndUpdate();
            }
    
            private DataTable GetTableByParentId(int parentId)
            {
                /*
                    -- 生成测试数据
                    IF OBJECT_ID('ICBOMGROUP') IS NOT NULL 
                        DROP TABLE ICBOMGROUP
                        
                    CREATE TABLE ICBOMGROUP (
                        FInterID INT
                      , FParentID INT
                      , FName VARCHAR(40)
                      , FNumber VARCHAR(40) )
    
                    INSERT ICBOMGROUP
                    SELECT 1039,0,'产品','0'     UNION ALL
                    SELECT 2296,0,'喷印机壳','1' UNION ALL
                    SELECT 6497,0,'丝印彩盒','2' UNION ALL
                    SELECT 7035,0,'外发加工','3' UNION ALL
                    SELECT 1041,1039,'VGA电视盒','01' UNION ALL
                    SELECT 1071,1041,'TV3488B系列','01.01' UNION ALL
                    SELECT 1140,1071,'TV2188E BOM','01.01.01' UNION ALL
                    SELECT 1144,1140,'普通订单','01.01.01.01' UNION ALL
                    SELECT 1146,1144,'TV2188E 中文BOM','01.01.01.01.01' UNION ALL
                    SELECT 1145,1140,'特殊订单','01.01.01.02' UNION ALL
                    SELECT 1129,1039,'XGA电视盒','02' UNION ALL
                    SELECT 1199,1129,'TV5811系列','02.02' UNION ALL
                    SELECT 1212,1199,'TV5811 BOM','02.02.01' UNION ALL
                    SELECT 2297,2296,'机壳-上盖','1.01' UNION ALL
                    SELECT 2308,2297,'GM998','01.01.01' UNION ALL
                    SELECT 2312,2308,'GM998上盖 灰色ABS/喷银色','1.01.01.01' UNION ALL
                    SELECT 7039,7035,'支架组件','3.01' UNION ALL
                    SELECT 7040,7039,'PD1048','3.01.01' UNION ALL
                    SELECT 7172,7040,'PD1048支架组件1','3.01.01.01'
                 */
                String connectionString = @"Server=XXY\SQLEXPRESS; Database=X; Integrated Security=SSPI";
                String commandText = "SELECT * FROM ICBOMGROUP WHERE FParentID = @ParentId";
    
                using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString))
                {
                    adapter.SelectCommand.Parameters.AddWithValue("@ParentId", parentId);
                    adapter.SelectCommand.CommandTimeout = 0;
    
                    DataSet ds = new DataSet();
                    adapter.Fill(ds);
    
                    return ds.Tables[0];
                }
            }
    
            private void BuildTreeView(TreeNodeCollection nodes, int parentId)
            {
                try
                {
                    DataTable dt = this.GetTableByParentId(parentId);
    
                    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
                        // this.BuildTreeView(node.Nodes, fPath); // 取消递归,在 BeforeExpand 事件中添加子级节点
                    }
                }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
    
            public TreeNode CreateLoadingNode()
            {
                // 创建一个特殊节点,它的存在标志它的父节点需要动态加载
                DataNode dataNode = new DataNode();
                dataNode.Type = this.LoadingKey;
                return dataNode;
            }
    
            private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
            {
                DataNode dataNode = (DataNode)e.Node;
    
                if (dataNode.Nodes.Count == 1 &&
                    ((DataNode)dataNode.Nodes[0]).Type == this.LoadingKey)
                {
                    // 若特殊节点存在,移除它,并为它的父节点创建子节点
                    dataNode.Nodes[0].Remove();
                    this.BuildTreeView(dataNode.Nodes, dataNode.Id);
                }
            }
        }
    
        public class DataNode : TreeNode
        {
            public Int32 Id { get; set; }
            public String Type { get; set; }
            public DataRow Row { get; set; }
            
    
            public DataNode() : base() { }
        }
    }
    

    知识改变命运,奋斗成就人生!
    • 已标记为答案 YiChun Chen 2009年10月12日 3:37
    2009年10月10日 4:52
    版主

全部回复

  • 你好!

    检查你的连接字符串是否正确,数据库服务器是否能正常连上,设置 cmd.CommandTimeout = 0; 这样就不会超时了

    知识改变命运,奋斗成就人生!
    2009年10月9日 7:32
    版主
  • X.X.Y版主,字符串连接是OK的,我自己创建了一个简单的数据库表,数据量少的时候,在测试运行的时候会很快通过,但当数据量过大,则会出现连接超时,以前在MSDN的回复说是用BeforeExpand事件,但不知道咋用,请老师指点
    2009年10月9日 7:38
  • 你好!

    你把下面这句加上

    cmd.CommandTimeout = 0; // 永不超时

    知识改变命运,奋斗成就人生!
    2009年10月9日 7:39
    版主
  • 那这样展开节点的效率会不会低噢?
    2009年10月9日 7:48
  • 能否请X.X.Y版主修改一下代码啊?这个问题问了很久了,困惑N久了..求救………………………………
    2009年10月9日 7:58
  • 你好!

    抱歉下午很忙没能及时回复你,下面我用目录的形式做了一个示例,希望对你有帮助。
    ------------------------------------------------------------------------------------------
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace DirectoryDemo
    {
        public partial class Form1 : Form
        {
            private String LoadingKey = "57868058-716C-4D36-B48E-D840AA2C50C3";
            private TreeView treeView1;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                this.BuildTreeView();
            }
    
            private void BuildTreeView()
            {
                if (this.treeView1 == null)
                {
                    this.treeView1 = new TreeView();
                    this.treeView1.Dock = DockStyle.Fill;
                    this.Controls.Add(this.treeView1);
                    this.treeView1.BeforeExpand += new TreeViewCancelEventHandler(treeView1_BeforeExpand);
                }
    
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        this.treeView1.BeginUpdate();
                        this.treeView1.Nodes.Clear();
                        this.BuildTreeView(this.treeView1.Nodes, dialog.SelectedPath);
                        this.treeView1.EndUpdate();
                    }
                }
            }
    
            private void BuildTreeView(TreeNodeCollection nodes, String directoryPath)
            {
                try
                {
                    // 这里这了提高效率一次只取一层节的数据不递归,若要换成数据道理一样。
                    foreach (String fPath in Directory.GetDirectories(directoryPath))
                    {
                        DirectoryInfo directoryInfo = new DirectoryInfo(fPath);
                        DirectoryNode directoryNode = new DirectoryNode();
                        directoryNode.Text = directoryInfo.Name;
                        directoryNode.Path = fPath;
                        directoryNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(directoryNode);
                        // this.BuildTreeView(node.Nodes, fPath); // 取消递归,在 BeforeExpand 事件中添加子级节点
                    }
                }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
    
            public TreeNode CreateLoadingNode()
            {
                // 创建一个特殊节点,它的存在标志它的父节点需要动态加载
                DirectoryNode directoryNode = new DirectoryNode();
                directoryNode.Type = this.LoadingKey;
                return directoryNode;
            }
    
            private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
            {
                DirectoryNode directoryNode = (DirectoryNode)e.Node;
    
                if (directoryNode.Nodes.Count == 1 &&
                    ((DirectoryNode)directoryNode.Nodes[0]).Type == this.LoadingKey)
                {
                    // 若特殊节点存在,移除它,并为它的父节点创建子节点
                    directoryNode.Nodes[0].Remove();
                    this.BuildTreeView(directoryNode.Nodes, directoryNode.Path);
                }
            }
        }
    
        public class DirectoryNode : TreeNode
        {
            public String Path { get; set; }
            public String Type { get; set; }
    
            public DirectoryNode() : base() { }
        }
    }
    


    知识改变命运,奋斗成就人生!
    2009年10月9日 12:40
    版主
  • 谢谢老师指点,偶明天上班的时候测试一下,,真的太感谢了,困惑偶一个多月了,真要好好看书,好好学习
    向老师学习
    2009年10月9日 14:33
  • String LoadingKey = "57868058-716C-4D36-B48E-D840AA2C50C3";
    这句话的意思看得不是很明白,能否老师就将我的那个数据库做个例子,今天早上一直在修改老师的代码,改了很久还是没能通过编译
    能否老师在自己的数据库上插入这些数据,测试一下,偶将SQL的插入语句贴粘在这里,请老师帮我修改如何修改偶原来的代码(1楼)才能实现这个效率问题?
    if object_id('ICBOMGROUP') is not null drop table ICBOMGROUP

    create table ICBOMGROUP(FInterID int,FParentID int,FName varchar(40),FNumber varchar(40))

    insert ICBOMGROUP
    select 1039,0,'产品','0'     union all
    select 2296,0,'喷印机壳','1' union all
    select 6497,0,'丝印彩盒','2' union all
    select 7035,0,'外发加工','3' union all
    select 1041,1039,'VGA电视盒','01' union all
    select 1071,1041,'TV3488B系列','01.01' union all
    select 1140,1071,'TV2188E BOM','01.01.01' union all
    select 1144,1140,'普通订单','01.01.01.01' union all
    select 1146,1144,'TV2188E 中文BOM','01.01.01.01.01' union all
    select 1145,1140,'特殊订单','01.01.01.02' union all
    select 1129,1039,'XGA电视盒','02' union all
    select 1199,1129,'TV5811系列','02.02' union all
    select 1212,1199,'TV5811 BOM','02.02.01' union all
    select 2297,2296,'机壳-上盖','1.01' union all
    select 2308,2297,'GM998','01.01.01' union all
    select 2312,2308,'GM998上盖 灰色ABS/喷银色','1.01.01.01' union all
    select 7039,7035,'支架组件','3.01' union all
    select 7040,7039,'PD1048','3.01.01' union all
    select 7172,7040,'PD1048支架组件1','3.01.01.01'

    2009年10月10日 2:36
  • LoadingKey 只是一个特殊标志,指示这个节点是否为特殊的节点,如果是特殊节点程序会从数据读取这个节点的子节点数据并创建数节点


    知识改变命运,奋斗成就人生!
    2009年10月10日 4:51
    版主
  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Data.SqlClient;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private String LoadingKey = "57868058-716C-4D36-B48E-D840AA2C50C3";
            private TreeView treeView1;
    
            public Form1()
            {
                InitializeComponent();
    
                this.BuildTreeView();
            }
    
            private void BuildTreeView()
            {
                if (this.treeView1 == null)
                {
                    this.treeView1 = new TreeView();
                    this.treeView1.Dock = DockStyle.Fill;
                    this.Controls.Add(this.treeView1);
                    this.treeView1.BeforeExpand += new TreeViewCancelEventHandler(treeView1_BeforeExpand);
                }
    
                this.treeView1.BeginUpdate();
                this.BuildTreeView(this.treeView1.Nodes, 0);
                this.treeView1.EndUpdate();
            }
    
            private DataTable GetTableByParentId(int parentId)
            {
                /*
                    -- 生成测试数据
                    IF OBJECT_ID('ICBOMGROUP') IS NOT NULL 
                        DROP TABLE ICBOMGROUP
                        
                    CREATE TABLE ICBOMGROUP (
                        FInterID INT
                      , FParentID INT
                      , FName VARCHAR(40)
                      , FNumber VARCHAR(40) )
    
                    INSERT ICBOMGROUP
                    SELECT 1039,0,'产品','0'     UNION ALL
                    SELECT 2296,0,'喷印机壳','1' UNION ALL
                    SELECT 6497,0,'丝印彩盒','2' UNION ALL
                    SELECT 7035,0,'外发加工','3' UNION ALL
                    SELECT 1041,1039,'VGA电视盒','01' UNION ALL
                    SELECT 1071,1041,'TV3488B系列','01.01' UNION ALL
                    SELECT 1140,1071,'TV2188E BOM','01.01.01' UNION ALL
                    SELECT 1144,1140,'普通订单','01.01.01.01' UNION ALL
                    SELECT 1146,1144,'TV2188E 中文BOM','01.01.01.01.01' UNION ALL
                    SELECT 1145,1140,'特殊订单','01.01.01.02' UNION ALL
                    SELECT 1129,1039,'XGA电视盒','02' UNION ALL
                    SELECT 1199,1129,'TV5811系列','02.02' UNION ALL
                    SELECT 1212,1199,'TV5811 BOM','02.02.01' UNION ALL
                    SELECT 2297,2296,'机壳-上盖','1.01' UNION ALL
                    SELECT 2308,2297,'GM998','01.01.01' UNION ALL
                    SELECT 2312,2308,'GM998上盖 灰色ABS/喷银色','1.01.01.01' UNION ALL
                    SELECT 7039,7035,'支架组件','3.01' UNION ALL
                    SELECT 7040,7039,'PD1048','3.01.01' UNION ALL
                    SELECT 7172,7040,'PD1048支架组件1','3.01.01.01'
                 */
                String connectionString = @"Server=XXY\SQLEXPRESS; Database=X; Integrated Security=SSPI";
                String commandText = "SELECT * FROM ICBOMGROUP WHERE FParentID = @ParentId";
    
                using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString))
                {
                    adapter.SelectCommand.Parameters.AddWithValue("@ParentId", parentId);
                    adapter.SelectCommand.CommandTimeout = 0;
    
                    DataSet ds = new DataSet();
                    adapter.Fill(ds);
    
                    return ds.Tables[0];
                }
            }
    
            private void BuildTreeView(TreeNodeCollection nodes, int parentId)
            {
                try
                {
                    DataTable dt = this.GetTableByParentId(parentId);
    
                    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
                        // this.BuildTreeView(node.Nodes, fPath); // 取消递归,在 BeforeExpand 事件中添加子级节点
                    }
                }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
    
            public TreeNode CreateLoadingNode()
            {
                // 创建一个特殊节点,它的存在标志它的父节点需要动态加载
                DataNode dataNode = new DataNode();
                dataNode.Type = this.LoadingKey;
                return dataNode;
            }
    
            private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
            {
                DataNode dataNode = (DataNode)e.Node;
    
                if (dataNode.Nodes.Count == 1 &&
                    ((DataNode)dataNode.Nodes[0]).Type == this.LoadingKey)
                {
                    // 若特殊节点存在,移除它,并为它的父节点创建子节点
                    dataNode.Nodes[0].Remove();
                    this.BuildTreeView(dataNode.Nodes, dataNode.Id);
                }
            }
        }
    
        public class DataNode : TreeNode
        {
            public Int32 Id { get; set; }
            public String Type { get; set; }
            public DataRow Row { get; set; }
            
    
            public DataNode() : base() { }
        }
    }
    

    知识改变命运,奋斗成就人生!
    • 已标记为答案 YiChun Chen 2009年10月12日 3:37
    2009年10月10日 4:52
    版主
  • 谢谢老师指点,测试成功通过了,另外还有一点我想问一下:
    如何判断在ICBOMGROUP表中的FInterID列,在对应的FParentID列不存在,就是判断该节点为该树节点的最后一个节点了.
    例如:

    ICBOMGROUP表
    FInterID FParentID
    1140       1138
    1145       1140

    1145在FParentID在不存在,就为该树节点的最后一个节点,如果该结点为末节点,则在该目录下添加第一个关联的标致节点(FBomNumber),比如说:
    ICBOM表
    FParentID   FBomNumber
    1145             BOM00145

    就在1145下节点添加一个BOM00145(text值),

    根据这个节点的text值,如何联动datagridview表中的相关数据噢,绑定?请老师指点
    2009年10月12日 7:28
  • 这个比较简单,你可以在SQL中来生成这个标志,程序中对这个标志判断就行了,

    SELECT FInterID
          ,FParentID
          ,FName
          ,FNumber
          ,ChildCount = (SELECT COUNT(1) FROM ICBOMGROUP WHERE FParentID = A.FInterID) -- 子节点个数,为 0 就是未级节点
      FROM ICBOMGROUP A
      WHERE FParentID = @ParentId 


    知识改变命运,奋斗成就人生!
    2009年10月12日 8:25
    版主
  • 根据这个节点的text值,如何联动datagridview表中的相关数据噢,绑定?请老师指点

    treeview与datagridview连动?

    2009年10月12日 23:37
  • 记得前些时候给你说过方法,你要自己多尝试,这样才进步得快。在 AfterSelect 事件中,获取选中节点的信息,根据这个信息获取需要绑定 DataGridView 的数据并绑定。


     


    知识改变命运,奋斗成就人生!
    2009年10月13日 1:37
    版主
  •   谢谢老师,偶自己会去尝试,现在碰到的这个问题,就是用[ChildCount]=0,早上测了一个上午,主要问题是这样子:
    因为第一个SQL语句:
    SELECT FInterID
          ,FParentID
          ,FName
          ,FNumber
          ,ChildCount = (SELECT COUNT(1) FROM ICBOMGROUP WHERE FParentID = A.FInterID) -- 子节点个数,为 0 就是未级节点
      FROM ICBOMGROUP A
    这只是ICBOMGROUP表,如果到了最后一个节点的时候,需要动态加载另外二个表的信息,现如今三个表的结构,:
    ICBOMGROUP表                                           ICBOM表                                                      t_ICItemCore
    FInterID FParentID              FParentID    FBOMNumber   FInterID FItemID                     FItemID   FName
    1140       1138                       1145          BOM00145         1160     0529                          0529        前壳
    1145       1140                       1145          BOM00146         1161     0530                          0530        后壳
     
    ICBOMGROUP表与ICBOM表关联FInterID=FParentID,
    ICBOM表与t_ICItemCore表关联FItemID=FItemID

    当ICBOMGROUP表中的FInterID(1145)为最后一个根结点,则在这个根结点下加载ICBOM表中(FBOMNumber列)+t_ICItemCore表(FName)
    我的思路是:
    构造一个表,再判断ICBOMGROUP表中的结点是否为最后一个结点,如果是,则加载这二个表的相关项,但怎么编译通过不了?
    我的代码如下:
    //构造表
            private DataTable fSampleDataSource;
            public DataTable SampleDataSource
            {
                get
                {
                   
                        SqlConnection thisconnection = new SqlConnection("server=192.100.3.3;database=GADMEIERP;uid=sa;pwd=;");
                        SqlCommand cmd = thisconnection.CreateCommand();
                        cmd.CommandType = CommandType.Text;
                        cmd.CommandText = "SELECT a.FInterID,b.FBOMNumber,b.FUseStatus,c.FNumber,c.FName FROM ICBOMGROUP a left outer join ICBOM b on a.FInterID=b.FParentID left outer join t_ICItemCore c on b.FItemID=c.FItemID  order by a.FNumber";
                        SqlDataAdapter adapter = new SqlDataAdapter();
                        adapter.SelectCommand = cmd;
                        DataSet ds = new DataSet();
                        adapter.Fill(ds);
                        this.fSampleDataSource = ds.Tables[0];
                        return fSampleDataSource;
                   
                }
            }

    判断最后节点
    private void BuildTreeView(TreeNodeCollection nodes, int parentId)
            {
                try
                {
                    DataTable dt = this.GetTableByParentId(parentId);

                    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
     
                        if ((Int32)dataRow["ChildCount"] == 0)
                          {
                            foreach (DataRow dyrow in SampleDataSource.Rows)
                               {
                                   TreeNode LastNode = new TreeNode();
     
                                   if ((Int32)dyrow["FInterID"] == (Int32)dataRow["FInterID"])
                                       {
     
                                          LastNode.Text = dyrow["FBOMNumber"].ToString();
                                          LastNode.Nodes.Add(this.CreateLoadingNode());
                                          dataNode.Nodes.Add(LastNode);
                                       }
                               }
                                    
                               
                         }
                  }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

    请老师指点下:
    最后的树结点效果:
    1145
     ---BOM00145(前壳)
     ---BOM00146(后壳)

    因为最后的BOM00145(前壳)等不在ICBOMGROUP表,如果将这二条列写在老师你写的那条SQL语句中,会出现
    1145
    ---BOM00145(前壳)
    1145
    ---BOM00146(后壳)

    早上测了一个上午,没有通过,请指导   
    2009年10月13日 3:04
  • 你好!

    你是不知道怎么判断未级节点吗?

    知识改变命运,奋斗成就人生!
    2009年10月13日 7:41
    版主
  • 最后末级节点,用的老师那个SQL语句判断ChildCount=0,就可以判断出来,但问题是在这个末节点下要加入的子节点,不是在ICBOMGROUP(原表)中了,而是数据库另外二个表中的相关数据了,这样的加法,我用的这样(构造了一个表,存另外二个表中的数据):
    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
     
                        if ((Int32)dataRow["ChildCount"] == 0)
                          {
                            foreach (DataRow dyrow in SampleDataSource.Rows)
                               {
                                   TreeNode LastNode = new TreeNode();
     
                                   if ((Int32)dyrow["FInterID"] == (Int32)dataRow["FInterID"])
                                       {
     
                                          LastNode.Text = dyrow["FBOMNumber"].ToString();
                                          LastNode.Nodes.Add(this.CreateLoadingNode());
                                          dataNode.Nodes.Add(LastNode);
                                       }
                               }
                                    
                               
                         }
    但是编译通过不了
    2009年10月13日 7:58
  • 什么错?


    知识改变命运,奋斗成就人生!
    2009年10月13日 8:21
    版主
  • 无法将treenode类型转化为datanode类型,出错提示在
    private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
            {
                DataNode dataNode = (DataNode)e.Node;//报错处:无法将treenode类型转化为datanode类型

                if (dataNode.Nodes.Count == 1 &&
                    ((DataNode)dataNode.Nodes[0]).Type == this.LoadingKey)
                {
                    // 若特殊节点存在,移除它,并为它的父节点创建子节点
                    dataNode.Nodes[0].Remove();
                    this.BuildTreeView(dataNode.Nodes, dataNode.Id);
                }
            }
    2009年10月13日 8:32
  • 可能是循环用得不对,展开的树节点不完整,,
    如果没用判断最后节点,则展开的节点完全是ICBOMGROUP表中的数据

    2009年10月13日 8:33
  •  if ((Int32)dataRow["ChildCount"] == 0)
                          {
                            foreach (DataRow dyrow in SampleDataSource.Rows)
                               {
                                   TreeNode LastNode = new TreeNode(); // 改成 DataNode LastNode = new DataNode();
     
                                   if ((Int32)dyrow["FInterID"] == (Int32)dataRow["FInterID"])
                                       {
     
                                          LastNode.Text = dyrow["FBOMNumber"].ToString();
                                          LastNode.Nodes.Add(this.CreateLoadingNode());
                                          dataNode.Nodes.Add(LastNode);
                                       }
                               }
                                    
                               
                         }

    知识改变命运,奋斗成就人生!
    2009年10月13日 8:36
    版主
  • 请问XXY版主,我这样用循环对不对,就是说在ICBOMGROUP表中的所有根节点都展开后,就是达到末节点后,再去添加其它二个表中的数据,这样循环是否是对的呢?
    2009年10月13日 8:53
  • 这样是可以的,但大部分时候并不是只有未级节点才会有二级分类节点。
    知识改变命运,奋斗成就人生!
    2009年10月13日 9:13
    版主
  • 那还得改,只有末级节点的时候才会有二级分类节点,我回去测试,自己动手,不明白的时候再请教老师
    真的感谢XXY版主这么多天以来对偶的帮助,谢谢

    2009年10月13日 9:21
  • XXY版主,晚上测到现在都没通过来着,这段语句无论怎么改,都无法将ICBOMGROUP表中的数据全部插入完后,判断到末节点,再插入另外一个数据库表中相关的数据
    语句如下:
     if ((Int32)dataRow["ChildCount"] == 0)
                          {
                            foreach (DataRow dyrow in SampleDataSource.Rows)
                               {
                                   TreeNode LastNode = new TreeNode(); // 改成 DataNode LastNode = new DataNode();
     
                                   if ((Int32)dyrow["FInterID"] == (Int32)dataRow["FInterID"])
                                       {
     
                                          LastNode.Text = dyrow["FBOMNumber"].ToString();
                                          LastNode.Nodes.Add(this.CreateLoadingNode());
                                          dataNode.Nodes.Add(LastNode);
                                       }
                               }
                                    
                               
                         }

    这段语句不能在ICBOMGROUP表判断末节点后,再插入其它表中的相关数据,请指点
    2009年10月13日 14:11
  • 什么问题?报什么错?
    知识改变命运,奋斗成就人生!
    2009年10月14日 1:38
    版主
  • 没有报任何错,但是得不到想要的结果,版主,这是你给出的其中一部分代码:
            private DataTable GetTableByParentId(int parentId)
            {
                /*
                    -- 生成测试数据
                    IF OBJECT_ID('ICBOMGROUP') IS NOT NULL
                        DROP TABLE ICBOMGROUP
                       
                    CREATE TABLE ICBOMGROUP (
                        FInterID INT
                      , FParentID INT
                      , FName VARCHAR(40)
                      , FNumber VARCHAR(40) )

                    INSERT ICBOMGROUP
                    SELECT 1039,0,'产品','0'     UNION ALL
                    SELECT 2296,0,'喷印机壳','1' UNION ALL
                    SELECT 6497,0,'丝印彩盒','2' UNION ALL
                    SELECT 7035,0,'外发加工','3' UNION ALL
                    SELECT 1041,1039,'VGA电视盒','01' UNION ALL
                    SELECT 1071,1041,'TV3488B系列','01.01' UNION ALL
                    SELECT 1140,1071,'TV2188E BOM','01.01.01' UNION ALL
                    SELECT 1144,1140,'普通订单','01.01.01.01' UNION ALL
                    SELECT 1146,1144,'TV2188E 中文BOM','01.01.01.01.01' UNION ALL
                    SELECT 1145,1140,'特殊订单','01.01.01.02' UNION ALL
                    SELECT 1129,1039,'XGA电视盒','02' UNION ALL
                    SELECT 1199,1129,'TV5811系列','02.02' UNION ALL
                    SELECT 1212,1199,'TV5811 BOM','02.02.01' UNION ALL
                    SELECT 2297,2296,'机壳-上盖','1.01' UNION ALL
                    SELECT 2308,2297,'GM998','01.01.01' UNION ALL
                    SELECT 2312,2308,'GM998上盖 灰色ABS/喷银色','1.01.01.01' UNION ALL
                    SELECT 7039,7035,'支架组件','3.01' UNION ALL
                    SELECT 7040,7039,'PD1048','3.01.01' UNION ALL
                    SELECT 7172,7040,'PD1048支架组件1','3.01.01.01'
                 */

                String connectionString = @"Server=XXY\SQLEXPRESS; Database=X; Integrated Security=SSPI";
                String commandText = "SELECT FInterID,FParentID,FName,FNumber ,ChildCount = (SELECT COUNT(1) FROMICBOMGROUP WHERE FParentID = A.FInterID) -- 子节点个数,为 0 就是未级节点FROM ICBOMGROUP A";

                using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString))
                {
                    adapter.SelectCommand.Parameters.AddWithValue("@ParentId", parentId);
                    adapter.SelectCommand.CommandTimeout = 0;

                    DataSet ds = new DataSet();
                    adapter.Fill(ds);

                    return ds.Tables[0];
                }
            }

            private void BuildTreeView(TreeNodeCollection nodes, int parentId)
            {
                try
                {
                    DataTable dt = this.GetTableByParentId(parentId);

                    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
                        // this.BuildTreeView(node.Nodes, fPath); // 取消递归,在 BeforeExpand 事件中添加子级节点
                    }
                }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

     如何判断点击的结点为末结点?如果是末结点,则在该结点下添加另一个表的相关信息?偶写的代码编译通过了,但是得不到想要的结果,偶的代码如下:
    foreach (DataRow dataRow in dt.Rows)
                    {
                        DataNode dataNode = new DataNode();
                        dataNode.Id = (Int32)dataRow["FInterID"];
                        dataNode.Text = dataRow["FName"].ToString();
                        dataNode.Row = dataRow;
                        dataNode.Nodes.Add(this.CreateLoadingNode()); // 添加一个特殊节点,它的存在标志它的父节点需要动态加载
                        nodes.Add(dataNode);
                        
                        if ((Int32)dataRow["ChildCount"] == 0)//我的编码
                          {
                            foreach (DataRow dyrow in SampleDataSource.Rows)
                               {
                                   DataNode LastNode = new DataNode ();

     
                                   if ((Int32)dyrow["FInterID"] == (Int32)dataRow["FInterID"])
                                       {
     
                                          LastNode.Text = dyrow["FBOMNumber"].ToString();
                                          LastNode.Nodes.Add(this.CreateLoadingNode());
                                          dataNode.Nodes.Add(LastNode);
                                       }
                               }
                                    
                               
                         }

    三个表的结果如下:
    ICBOMGROUP表(主表)                                     ICBOM表                                                      t_ICItemCore
    FInterID FParentID              FParentID    FBOMNumber   FInterID FItemID                     FItemID   FName
    1140       1138                       1145          BOM00145         1160     0529                          0529        前壳
    1145       1140                       1145          BOM00146         1161     0530                          0530        后壳
         
    当判断完ICBOMGROUP的末结点后,添加ICBOM表中FBOMNumber列,条件是ICBOMGROUP表的FInterID关联ICBOM表的FParentID
    要的树结点结果如下:
    因为在ICBOMGROUP表中的FInterID列中1145在FParentID列中找不到对应的数据,所以为末节点,当它是末节点,则在它的子节点中添加ICBOM表中的FBOMNumber列和t_ICItemCore表中的FName列

    1145
     ---BOM00145(前壳)
     ---BOM00146(后壳)

    请老师指点,偶循环用得不对,判断条件也写错了
    2009年10月14日 2:01
  • ICBOM 表的数据你就没有获取,怎么会有呢
    知识改变命运,奋斗成就人生!
    2009年10月14日 2:18
    版主
  • 我构建了一个  SampleDataSource表,代码如下:
    //构造表
            private DataTable fSampleDataSource;
            public DataTable SampleDataSource
            {
                get
                {
                   
                        SqlConnection thisconnection = new SqlConnection("server=192.100.3.3;database=GADMEIERP;uid=sa;pwd=;");
                        SqlCommand cmd = thisconnection.CreateCommand();
                        cmd.CommandType = CommandType.Text;
                        cmd.CommandText = "SELECT a.FInterID,b.FBOMNumber,b.FUseStatus,c.FNumber,c.FName FROM ICBOMGROUP a left outer join ICBOM b on a.FInterID=b.FParentID left outer join t_ICItemCore c on b.FItemID=c.FItemID  order by a.FNumber";
                        SqlDataAdapter adapter = new SqlDataAdapter();
                        adapter.SelectCommand = cmd;
                        DataSet ds = new DataSet();
                        adapter.Fill(ds);
                        this.fSampleDataSource = ds.Tables[0];
                        return fSampleDataSource;
                   
                }
            }
    就是不知道如何判断ICBOMGROUP表中的结点为末节点,如果是末节点,该怎么添加这个构造表的数据FBOMNumber列?
    2009年10月14日 2:21