Freigeben über


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 https://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

  • Anonymous
    September 18, 2005
    Orangy asks:

    Hello, thanks for nice articles. Could you please write one about creating combobox-style...
  • Anonymous
    September 18, 2005
    Orangy asks:

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