将TreeView控件绑定到ComboBox控件后,设置控件的DropDownStyle为默认的DropDown,然后选择TreeView节点后,节点文本能够显示在ComboBox中,但是如果DropDownStyle为DropDownList,则选择TreeView节点后,节点文本不会显示在ComboBox中,不知道代码还缺少什么。我的代码和运行结果如下:using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing;namespace ComboBoxTreeViewControl
{
    public class ComboBoxTreeView : ComboBox
    {
        private const int WM_LBUTTONDOWN = 0x201, WM_LBUTTONDBLCLK = 0x203;
        ToolStripControlHost treeViewHost;
        ToolStripDropDown dropDown;
        public ComboBoxTreeView()
        {
            TreeView treeView = new TreeView();
            treeView.AfterSelect += new TreeViewEventHandler(treeView_AfterSelect);
            treeView.BorderStyle = BorderStyle.None;            treeViewHost = new ToolStripControlHost(treeView);
            dropDown = new ToolStripDropDown();
            dropDown.Width = this.Width;
            dropDown.Items.Add(treeViewHost);
        }
        public void treeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.Text = TreeView.SelectedNode.Text;
            dropDown.Close();
        }
        public TreeView TreeView
        {
            get { return treeViewHost.Control as TreeView; }
        }
        private void ShowDropDown()
        {
            if (dropDown != null)
            {
                treeViewHost.Size = new Size(DropDownWidth - 2, DropDownHeight);
                dropDown.Show(this, 0, this.Height);
            }
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
            {
                ShowDropDown();
                return;
            }
            base.WndProc(ref m);
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (treeViewHost != null)
                {
                    treeViewHost.Dispose();
                    treeViewHost = null;
                }                if (dropDown != null)
                {
                    dropDown.Dispose();
                    dropDown = null;
                }
            }
            base.Dispose(disposing);
        }
    }
}
截图了,但是不知道怎么贴进来。

解决方案 »

  1.   

    参考C# WinForm开发系列 - ComboBox
      

  2.   

    下载了你提供的代码,将DropDownStyle设置为DropDownList,存在同样的问题。
      

  3.   

    你的代码不是继承ComboBox,所以没有DropDownStyle属性,我需要这样的设置
      

  4.   

    DropDownStyle属性, 把那个TextBox设置成只读看看, 然后自己处理treeview控件的选择事件
      

  5.   

    做过类型的程式序
    你先定义一个数据源属性,把数据添加到TreeView显示,同时也要添加到ComboBox的,选择树节点时,
    写  base.SelectedValue
    就好了!!!
      

  6.   


    base.SelectedValue=TreeView.SelectedNode.Text
      

  7.   

    谢谢peterb,你提供的方法应该可以实现类似功能,但我更希望是用DropDownStyle属性来实现。
    另外,MiloSoft说的定义数据源属性,是怎么定义的?谢谢指教!
      

  8.   

    2楼的空间用法和COMBOBOX是一样的,如果去获取TREE,用递归,其他方法一样
      

  9.   

    下面只是个示例,比较简单,请参考~1.控件代号
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;namespace WindowsApplication26
    {
        public class ComboBoxTreeView : ComboBox
        {
            private const int WM_LBUTTONDOWN = 0x201, WM_LBUTTONDBLCLK = 0x203;
            ToolStripControlHost treeViewHost;
            ToolStripDropDown dropDown;
            public ComboBoxTreeView()
            {
                TreeView treeView = new TreeView();
                treeView.AfterSelect += new TreeViewEventHandler(treeView_AfterSelect);
                treeView.BorderStyle = BorderStyle.None;            treeViewHost = new ToolStripControlHost(treeView);
                dropDown = new ToolStripDropDown();
                dropDown.Width = this.Width;
                dropDown.Items.Add(treeViewHost);
                this.DataSourceChanged += new EventHandler(ComboBoxTreeView_DataSourceChanged);
            }        void ComboBoxTreeView_DataSourceChanged(object sender, EventArgs e)
            {
                if (base.DataSource is List<string>)
                {
                    List<string> items = base.DataSource as List<string>;
                    foreach (string str in items)
                    {
                        TreeView.Nodes.Add(str);
                    }
                }
            }
            public void treeView_AfterSelect(object sender, TreeViewEventArgs e)
            {
                //如果设定了base.ValueMember 才可以用 SelectedValue           
                this.SelectedItem = TreeView.SelectedNode.Text;
                dropDown.Close();
            }
            public TreeView TreeView
            {
                get { return treeViewHost.Control as TreeView; }
            }
            private void ShowDropDown()
            {
                if (dropDown != null)
                {
                    treeViewHost.Size = new Size(DropDownWidth - 2, DropDownHeight);
                    dropDown.Show(this, 0, this.Height);
                }
            }
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
                {
                    ShowDropDown();
                    return;
                }
                base.WndProc(ref m);
            }
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (treeViewHost != null)
                    {
                        treeViewHost.Dispose();
                        treeViewHost = null;
                    }                if (dropDown != null)
                    {
                        dropDown.Dispose();
                        dropDown = null;
                    }
                }
                base.Dispose(disposing);
            }    }
    }
    2.使用的代码
    private void Form1_Load(object sender, EventArgs e)
            {
                List<string> datasource = new List<string>();
                datasource.Add("节点0");
                datasource.Add("节点1");
                datasource.Add("节点2");
                datasource.Add("节点3");
                comboBoxTreeView1.DataSource = datasource;
            }
      

  10.   

    谢谢!按照MiloSoft是可以实现我需要的DropDownList功能,不过当存在很多层子节点时,该如何添加数据到DataSource中?
      

  11.   

    数据源用一个DatabTable或者List里,用递归查找到每个节点的子节点,添加即可
      

  12.   

    不好意识,还是不是特别明白。我感觉你提供的代码是先在把值加载到Datatable中,但是多层子节点的好像应该是先添加TreeNode吧。该怎么加?
      

  13.   

     private DataTable GetTable(string sql)
            {
                using (OracleConnection conn = new OracleConnection("Data Source=ORCL;User ID=TODAI;Password=TODAI"))
                {
                    DataTable dt = new DataTable();
                    OracleDataAdapter da = new OracleDataAdapter(sql,conn);
                    da.Fill(dt);
                    return dt;
                }
            }private void yuangongjiansuo_Load(object sender, EventArgs e)
            {
                CreateTable();
                CreateTree();
            }
            private DataTable dtTree = null;
            private DataView dv = null;        private void CreateTable()
            {
                OracleConnection conn = new OracleConnection("Data Source=orcl;User ID=TODAI;Password=TODAI");
                conn.Open();
                string sss = "Select DEPTID,DEPTNAME,PARENT_DEPT_ID from HR_DEPARTMENT";
                OracleDataAdapter kkk = new OracleDataAdapter(sss, conn);
                DataSet ds = new DataSet();
                kkk.Fill(ds);
                dtTree = ds.Tables[0];
            }
            private void CreateTree()
            {
                dv = dtTree.DefaultView;
                dv.Sort = "PARENT_DEPT_ID   ASC";
                DataRowView[] arrDRV = dv.FindRows(0);
                if (arrDRV.Length == 0) return;
                TreeNode tnNew = null;
                foreach (DataRowView drv in arrDRV)
                {
                    tnNew = treeView1.Nodes.Add(drv.Row["DEPTNAME"].ToString());
                    tnNew.Tag = drv.Row["DEPTID"].ToString();
                    CreateTreeNode(ref   tnNew);
                }
                this.treeView1.ExpandAll();
            }
            private void CreateTreeNode(ref   TreeNode tnParent)
            {
                DataRowView[] arrDRV = dv.FindRows(tnParent.Tag);
                if (arrDRV.Length == 0) return;
                TreeNode tnNew = null;
                foreach (DataRowView drv in arrDRV)
                {
                    tnNew = tnParent.Nodes.Add(drv.Row["DEPTNAME"].ToString());
                    tnNew.Tag = drv.Row["DEPTID"].ToString();
                    CreateTreeNode(ref   tnNew);
                }
            }   我直接从数据库调用的代码,希望对LZ有帮助。
      

  14.   

    源码如下:using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Data;
    using System.ComponentModel;namespace ComboBoxTreeViewCOM
    {
        public class ComboBoxTreeView : ComboBox
        {
            private const int WM_LBUTTONDOWN = 0x201;
            private const int WM_LBUTTONDBLCLK = 0x203;
            private ToolStripControlHost m_pTreeViewControlHost = null;
            private ToolStripDropDown    m_pToolStripDropDown = null;
            private DataView             m_pDataView_TreeView = null;
            private string               m_strIDControl = string.Empty;
            private string               m_strIDParent = string.Empty;
            private string               m_strShowName = string.Empty;
            private bool                 m_isParentNodeSelectable = false;
            private bool                 m_isAllowNullValue = true;        /// <summary>
            /// 构造函数
            /// </summary>
            public ComboBoxTreeView()
            {
                TreeView oTreeView = new TreeView();
                oTreeView.AfterSelect += new TreeViewEventHandler(TreeView_AfterSelect);
                oTreeView.BorderStyle = BorderStyle.None;            this.m_pTreeViewControlHost = new ToolStripControlHost(oTreeView);
                this.m_pToolStripDropDown = new ToolStripDropDown();
                this.m_pToolStripDropDown.Width = this.Width;
                this.m_pToolStripDropDown.Items.Add(m_pTreeViewControlHost);
                this.DataSourceChanged += new EventHandler(ComboBoxTreeView_DataSourceChanged);
            }        #region 组件公共属性
                /// <summary>
                /// 获取TreeView控件
                /// </summary>
                [Description("获取TreeView控件")]
                public TreeView TreeView
                {
                    get
                    {
                        return m_pTreeViewControlHost.Control as TreeView;
                    }
                }            /// <summary>
                /// 控件下拉框显示内容名称
                /// </summary>
                [Description("控件下拉框显示内容名称")]
                [DefaultValue("string.Empty")]
                public string ShowName
                {
                    get
                    {
                        return this.m_strShowName;
                    }
                    set
                    {
                        this.m_strShowName = value;
                    }
                }            /// <summary>
                /// 组件IDControl属性
                /// </summary>
                [Description("组件IDControl属性")]
                [DefaultValue("string.Empty")]
                public string IDControl
                {
                    get 
                    {
                        return this.m_strIDControl;
                    }
                    set
                    {
                        this.m_strIDControl =value;
                    }
                }            /// <summary>
                /// 组件ParentID属性
                  /// </summary>
                [Description("组件ParentID属性")]
                [DefaultValue("string.Empty")]
                public string IDParent
                {
                    get
                    {
                        return this.m_strIDParent;
                    }
                    set
                    {
                        this.m_strIDParent = value;
                    }
                }            /// <summary>
                /// 父节点是否可选
                /// </summary>
                [Description("父节点是否可选")]
                [DefaultValue("false")]
                public bool ParentNodeSelectable
                {
                    get
                    {
                        return this.m_isParentNodeSelectable;
                    }
                    set
                    {
                        this.m_isParentNodeSelectable = value;
                    }
                }            /// <summary>
                /// 是否允许空值
                /// </summary>
                [Description("是否允许空值")]
                [DefaultValue("true")]
                public bool AllowNullValue
                {
                    get
                    {
                        return this.m_isAllowNullValue;
                    }
                    set
                    {
                        this.m_isAllowNullValue = value;
                    }
                }
            #endregion        /// <summary>
            /// 重载ComboBox的DataSourceChanged事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ComboBoxTreeView_DataSourceChanged(object sender, EventArgs e)
            {
                try
                {
                    DataTable pDataTable_TreeView = null;
                    DataRowView[] arrDataRowView = null;
                    TreeNode pTreeNode_New = null;                pDataTable_TreeView = this.DataSource as DataTable;                if (pDataTable_TreeView == null)
                        return;                m_pDataView_TreeView = pDataTable_TreeView.DefaultView;
                    m_pDataView_TreeView.Sort = m_strIDParent + @" ASC";                //添加用地分类,从0开始
                    arrDataRowView = m_pDataView_TreeView.FindRows(0);
                    if (arrDataRowView.Length > 0)
                    {
                        foreach (DataRowView pDataRowView in arrDataRowView)
                        {
                            pTreeNode_New = this.TreeView.Nodes.Add(pDataRowView.Row[m_strShowName].ToString());
                            pTreeNode_New.Tag = pDataRowView.Row[m_strIDControl].ToString();
                            CreateTreeNode(ref  pTreeNode_New);
                        }
                    }                ///展开所有节点
                    this.TreeView.ExpandAll();
                }
                catch
                {
                }
            }        /// <summary>
            /// 添加节点
            /// </summary>
            /// <param name="pTreeNode_Parent"></param>
            private void CreateTreeNode(ref TreeNode pTreeNode_Parent)
            {
                try
                {
                    DataRowView[] arrDataRowView_TreeNodeTag = m_pDataView_TreeView.FindRows(pTreeNode_Parent.Tag);
                    if (arrDataRowView_TreeNodeTag.Length == 0)
                        return;                TreeNode pTreeNode_New = null;
                    foreach (DataRowView pDataRowView in arrDataRowView_TreeNodeTag)
                    {
                        pTreeNode_New = pTreeNode_Parent.Nodes.Add(pDataRowView.Row[m_strShowName].ToString());
                        pTreeNode_New.Tag = pDataRowView.Row[m_strIDControl].ToString();
                        CreateTreeNode(ref  pTreeNode_New);
                    }
                }
                catch
                {
                }
            }        /// <summary>
            /// 重构TreeView控件的AfterSelect事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void TreeView_AfterSelect(object sender, TreeViewEventArgs e)
            {
                try
                {
                    if (this.m_isParentNodeSelectable == false && TreeView.SelectedNode != null && (TreeView.SelectedNode.Nodes == null || TreeView.SelectedNode.Nodes.Count == 0))
                    {
                        //如果设定了base.ValueMember才可以用SelectedValue
                        if (string.IsNullOrEmpty(this.ValueMember) == false)
                        {
                            this.SelectedValue = TreeView.SelectedNode.Text;
                        }
                        else
                        {
                            this.SelectedItem = TreeView.SelectedNode.Text;
                        }
                        m_pToolStripDropDown.Close();
                    }
                    else if (this.m_isParentNodeSelectable == true && TreeView.SelectedNode != null)
                    {
                        //如果设定了base.ValueMember才可以用SelectedValue
                        if (string.IsNullOrEmpty(this.ValueMember) == false)
                        {
                            this.SelectedValue = TreeView.SelectedNode.Text;
                        }
                        else
                        {
                            this.SelectedItem = TreeView.SelectedNode.Text;
                        }
                        m_pToolStripDropDown.Close();
                    }
                }
                catch
                {
                }
            }        /// <summary>
            /// 显示下拉框
            /// </summary>
            private void ShowDropDown()
            {
                if (m_pToolStripDropDown != null)
                {
                    m_pTreeViewControlHost.Size = new Size(DropDownWidth - 2, DropDownHeight);
                    m_pToolStripDropDown.Show(this, 0, this.Height);
                }
            }        /// <summary>
            /// 重载WndProc方法
            /// </summary>
            /// <param name="m"></param>
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
                {
                    ShowDropDown();
                    return;
                }
                base.WndProc(ref m);
            }        /// <summary>
            /// 重载Dispose方法
            /// </summary>
            /// <param name="disposing"></param>
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (m_pTreeViewControlHost != null)
                    {
                        m_pTreeViewControlHost.Dispose();
                        m_pTreeViewControlHost = null;
                    }                if (m_pToolStripDropDown != null)
                    {
                        m_pToolStripDropDown.Dispose();
                        m_pToolStripDropDown = null;
                    }
                }
                base.Dispose(disposing);
            }
        }
    }
      

  15.   

    在窗体中应用如下:
    private void Form1_Load(object sender, EventArgs e)
    {
        BindData();
    }
    private void BindData()
    {
        DataTable pDataTable_TreeView = GetTable("SELECT DM, DM & NAME As DMNAME , SJDM FROM ZD_TDLYFL ORDER BY DM, JB, XH");
        if (pDataTable_TreeView != null)
        {
            this.comboBoxTreeView1.DataSource = pDataTable_TreeView;
            this.comboBoxAdvTree1.DataSource = pDataTable_TreeView;
            this.comboBoxAdvTreeViewEx1.DataSource = pDataTable_TreeView;
        }
    }private DataTable GetTable(string strSQL)
    {
        OleDbConnection pOleDbConnection;    try
        {
            if (ConnectAccessDatabase("", out pOleDbConnection) && pOleDbConnection != null)
            {
                DataTable pDataTable = new DataTable();
                OleDbDataAdapter pOleDbDataAdapter = new OleDbDataAdapter(strSQL, pOleDbConnection);
                pOleDbDataAdapter.Fill(pDataTable);
                return pDataTable;
            }
            else
            {
                return null;
            }
        }
        catch
        {
            return null;
        }
    }#region 打开Access数据库连接,并返回OleDbConnection连接对象
    public static bool ConnectAccessDatabase(string strAccessFullPath,
                                             out OleDbConnection oDBConn)
    {
        string strConnection = string.Empty;    try
        {
            strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + & strAccessFullPath + ";Jet OLEDB:Engine Type=5;";        oDBConn = new OleDbConnection();
            oDBConn.ConnectionString = strConnection;
            oDBConn.Open();        if (oDBConn != null && oDBConn.State == ConnectionState.Open)
            {
                return true;
            }
            else
            {
                oDBConn = null;
                return false;
            }
        }
        catch
        {
            oDBConn = null;
            return false;
        }
    }
    #endregion
      

  16.   

    MiloSoft和laoban108,谢谢二位的指点。能否再帮帮忙,我现在又遇到一个新问题,就是用鼠标滚轮时,当设置父节点不能选择时,当鼠标滚轮或者按下上下箭头到父节点位置时父节点的Text依然会显示在控件的Text中,如何控制滚轮或者上下箭头不能选择父节点。谢谢!