Introduction
This article presents an extension of the .NET ComboBox
which provides custom drop-downs. The control can automatically add a resizer grip at the bottom of a drop-down.
Design
Custom drop-down functionality can be achieved using the .NET ToolStripDropDown
and ToolStripControlHost
classes. These two classes are great because they prevent application forms from becoming inactive during drop-down. The custom popup functionality required by this control has been encapsulated within the class PopupControl
(a new addition since the original article posting).
In addition to facilitating this control, the PopupControl
class can be used to provide drop-down support in your own controls. The PopupControl
also integrates the drop-down resize support (now without the need for a nested resizable container, see below for details).
Previously the drop-down control was resizable by nesting a resizable container. This was an okay solution (because it worked) but it caused some redraw errors during resize operations. The resize functionality has now been significantly improved, and it is now also possible to define which sides of the drop-down are resizable (if any). Resizing can now also be done by dragging the resizable edges of the drop-down. The new resize functionality is achieved by intercepting Win32 hit testing messages, and responding appropriately based upon the set PopupResizeMode
property.
The following UML class diagram provides an overview of the presented classes:
Using the Code
As with most controls, this control can be created dynamically at runtime, or by using the Visual C# IDE designer's drag and drop features. During runtime, the property DropDownControl
must be assigned to an instance of another control. The assigned control must not be contained elsewhere as this will cause problems.
Most drop-down controls appear better when their borders are removed.
namespace CustomComboDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataGridView gridView = new DataGridView();
gridView.BorderStyle = BorderStyle.None;
gridView.Columns.Add("Column1", "Column 1");
gridView.Columns.Add("Column2", "Column 2");
gridView.Columns.Add("Column3", "Column 3");
gridView.Columns.Add("Column4", "Column 4");
gridView.Columns.Add("Column5", "Column 5");
this.customComboBox1.DropDownControl = gridView;
UserControl1 userControl = new UserControl1();
userControl.BorderStyle = BorderStyle.None;
this.customComboBox2.DropDownControl = userControl;
RichTextBox richTextBox = new RichTextBox();
richTextBox.BorderStyle = BorderStyle.None;
this.customComboBox3.DropDownControl = richTextBox;
}
}
}
Points of Interest
When writing the code, I found that dropped-down controls were not retrieving immediate input focus. This problem occurs because even though the drop-down code is ignored during the Win32 message handler, the standard win32 drop-down still appears (1x1 pixels). To avoid this, a timer is created which forces the dropped-down control to be focused after the default win32 drop-down has been focused. Once the timer has done its job, it disables itself.
History
- 22nd April, 2008: Original version posted
- 29th April, 2008: Updated download files
- Fixed a bug that was pointed out by Adam Hearn
- 17th June, 2008: Various changes
- Improved design
- Odd drawing effects during drop-down resize have now been significantly improved
- Added
PopupControl
for general custom drop-down support - Added download files: Version 2
- 28th June, 2008: Updated download files for Version 2
- 15th July, 2008: Updated to version 2.1.
- Many thanks to member “Leon v Wyk” for this update
- The improved version now hides incompatible properties from the Visual Studio .IDE properties panel which was causing confusion
- 21st June, 2009: Updated to version 2.2
- Updated source, demo project and UML overview diagram
- Fixed bug found by CodeProject member “dokmanov”
Whilst the “DropDownClosed
” event was being fired when the drop down arrow was used to close the drop down, it was not being fired when the drop down was closed by clicking in the form area