Getting ComboBox to show a TreeView (Whidbey)


I tend to shy away from Whidbey only discussions here, but I've been asked a couple times how to get a combobox to show a treeview - so I thought I'd share with y'all what I whipped up in 20min.  The interesting thing here is what you can do with a ToolStripDropDown and ToolStripControlHost.  The ToolStripDropDown is a special kind of toplevel window (just like a form), and the ToolStripControlHost is a class that allows you to host arbitrary Controls within a ToolStrip/ToolStripDropDown

As always, if you have problems with these classes, we're eager to get your feedback.

             public Form1() {

                  InitializeComponent();
                  MyTreeViewCombo treeCombo = new MyTreeViewCombo();

                  // note: you may have to add these in Form.Load so the horizontal scrollbar doesnt appear
                  // See http://blogs.msdn.com/subhagpo/archive/2004/07/30/202665.aspx

                  treeCombo.TreeView.Nodes.Add("one");
                  treeCombo.TreeView.Nodes.Add("two");
                  treeCombo.TreeView.Nodes.Add("three");
 
                 this.Controls.Add(treeCombo);

            }

            public class MyTreeViewCombo : ComboBox {

                  ToolStripControlHost treeViewHost;
                  ToolStripDropDown dropDown;
                  public MyTreeViewCombo() {

                        TreeView treeView = new TreeView();
                        treeView.BorderStyle = BorderStyle.None;
                        treeViewHost = new ToolStripControlHost(treeView);

                        // create drop down and add it

                        dropDown = new ToolStripDropDown();
                       
dropDown.Items.Add(treeViewHost);

                  }

                  public TreeView TreeView {
                        get { return treeViewHost.Control as TreeView; }
                  }

                  private void ShowDropDown() {
                        if (dropDown != null) {
                           treeViewHost.Width = DropDownWidth;
                           treeViewHost.Height = DropDownHeight;
                           dropDown.Show(this, 0, this.Height);
                        }

                  }

                  private const int WM_USER = 0x0400,
                                    WM_REFLECT = WM_USER + 0x1C00,
                                    WM_COMMAND = 0x0111,
              
                      CBN_DROPDOWN = 7;

                  public static int HIWORD(int n) {
                        return (n >> 16) & 0xffff;
                  }

                  protected override void WndProc(ref Message m) {
                        if (m.Msg == ( WM_REFLECT + WM_COMMAND)) {
                              if (HIWORD((int)m.WParam) == CBN_DROPDOWN) {  
     
                              ShowDropDown();
                                    return;

                              }
                        }
                        base.WndProc(ref m);
                  }

                  // Edit: 10:37, remember to dispose the dropdown as it's not in the control collection. 
                  protected override void Dispose(bool disposing) {
                      if (disposing) { 
                         if (dropDown != null) {
                             dropDown.Dispose();
                             dropDown = null;
                         }
                       }
                       base.Dispose(disposing);
                   }
            }
      }

Comments (2)
  1. jfo's coding says:

    Orangy asks:

    Hello, thanks for nice articles. Could you please write one about creating combobox-style…

  2. jfo's coding says:

    Orangy asks:

    Hello, thanks for nice articles. Could you please write one about creating combobox-style…

Comments are closed.

Skip to main content