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");
}
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); } } }