Click here to Skip to main content
Click here to Skip to main content

Customizable ComboBox Drop-Down

By , 21 Jun 2009
 
Sample Image

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:

uml-overview.png

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)
        {
            // Dynamically created controls.

            // Create grid view control.
            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;

            // Create user control.
            UserControl1 userControl = new UserControl1();
            userControl.BorderStyle = BorderStyle.None;
            this.customComboBox2.DropDownControl = userControl;

            // Create rich textbox control.
            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

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Lea Hayes
Software Developer Rotorz Limited
United Kingdom United Kingdom
I have been fascinated by software and video games since a young age when I was given my first computer, a Dragon 32. Since then I have experimented with numerous methods of development ranging from point-and-click type packages to C++. I soon realized that software development was what I wanted to do.
 
Having invested a lot of time into programming with various languages and technologies I now find it quite easy to pickup new ideas and methodologies. I relish learning new ideas and concepts.
 
Throughout my life I have dabbled in game and engine development. I was awarded a first for the degree "BEng Games and Entertainment Systems Software Engineering" at the University of Greenwich. It was good to finally experience video games from a more professional perspective.
 
Due to various family difficulties I was unable to immediately pursue any sort of software development career. This didn't stop me from dabbling though!
 
Since then I formed a company to focus upon client projects. Up until now the company has primarily dealt with website design and development. I have since decided that it would be fun to go back to my roots and develop games and tools that other developers can use for their games.
 
We have recently released our first game on iPhone/iPad called "Munchy Bunny!" (see: http://itunes.apple.com/us/app/munchy-bunny!/id516575993?mt=8). We hope to expand the game and release to additional platforms.
 
Also, check out our tile system extension for Unity! (see: http://rotorz.com/tilesystem/)
Follow on   Twitter   Google+

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionContextMenuStrip on control in dropdownmemberwolfgang_hg26-Apr-13 4:03 
This might be helpful for others, so I post it here: If you place a control with a ContextMenuStrip in the dropdown, the dropdown will hide if you open the ContextMenuStrip.
 

The workaround is found here:
http://stackoverflow.com/questions/3062353/show-contextmenustrip-from-toolstripdropdown-without-dismissing-toolstripdropdow[^]
 
To sum it up: when rightclicking the control, set "PopUpControl.m_dropDown.AutoClose = false". After closing the ContextMenuStrip, reset this property to "true".
 
Hope this is helpful
 
Wolfgang
Questionautocomplete modememberalejandra004-Mar-13 0:42 
I have this control with a listBox (ListComboBox.cs) and I change the property autocomplete mode and autocomplete source of CustomComboBox.cs but when I execute the control in WindowsAppForm, not autocomplete Frown | :(
 

Can you help me? Thanks!!
Questiondatasource no muestra informacionmemberalfred03-Oct-12 15:06 
buenas tardes, esta excelente este articulo pero por mas que le busque no puede hacer que mostrara la informacion por mediod e un datasource en vez de agregar los items, espero y que me puedan ayudar con esto, ya que mi intencion es agregar un listbox por medio del datasource para ir filtrando los resultados segun loq ue va capturando el usuario....
GeneralMy vote of 5mvpKanasz Robert27-Sep-12 11:01 
good job
QuestionFocus problemmembergeorgegarvasis7-Apr-12 1:24 
Hi Lea,
 
i override the OnkeyPress event of combbox for searching the user input item from the datagrid.it is searching fine but control lost focus to datagrid after inputting the first character ,so i should click again to the combobox for show the cursor.i want to show the cursor and fcous to combobox even mouse hover in the datagrid( same like normal combobox).
 
can u guide me to solve this problem.
 

following are the new code i implemented into ur control.
protected override void OnKeyPress(KeyPressEventArgs e)
{
string strInput = "";
 
if (!Char.IsControl(e.KeyChar))
{
strInput = this.Text + e.KeyChar.ToString();
//Filter data
FilterData(strInput);
if (IsDroppedDown == false)
{
ShowDropDown();
}
if (dgMultiColumn.Rows.Count > 0)
{
dgMultiColumn.Rows[0].Selected = true;
//this.Focus();
this.Text = dgMultiColumn.Rows[0].Cells[DisplayColumn].Value.ToString();
this.SelectionStart = strInput.Length;
this.SelectionLength = Text.Length - strInput.Length;
 
//ShowCaret(this.Handle);
}
}
 
if ((e.KeyChar == (char)(Keys.Back)) && // A Backspace Key is hit
(Convert.ToBoolean(this.SelectionStart))) // And the SelectionStart is positive
{
string strFind = this.Text.Substring(0, this.SelectionStart - 1);
this.SelectionStart = strFind.Length;
this.SelectionLength = Text.Length - strFind.Length;
 
}
 
e.Handled = true;
base.OnKeyPress(e);
}
 
private void FilterData(string strInput)
{
try
{
SetFilter(strInput);//this.Text);
if (dgMultiColumn.Rows.Count> 0)
{
dgMultiColumn.Rows[0].Selected = true;
//this.Text = dgMultiColumn.Rows[0].Cells[DisplayColumn].Value.ToString();
//this.Focus();
//this.SelectionStart = strInput.Length;
//this.SelectionLength = Text.Length - strInput.Length;
}
//this.Focus();
}
catch
{
}
}
 
private void SetFilter(string filterText)
{
string strFilterColumn;
try
{
if (filterText.Trim().Length >0 && dgMultiColumn.Columns.Count> 0)
{
strFilterColumn = dgMultiColumn.Columns[_DisplayColumn].DataPropertyName;
_BindingSource.Filter = strFilterColumn + string.Format("LIKE '%{0}%'", filterText);
}
else
{
_BindingSource.Filter = null;
}
}
catch
{
}
}
GeneralBinding DataGridviewmemberbbls198324-Mar-11 17:20 
There is a bug that binding the DatagridView ,set "gridview.datasoure=DataTable " and PopControl doesnt show the data!
no

GeneralMy vote of 5memberMark Guo1-Feb-11 16:10 
I like it
GeneralMsgBox message conflict with WndProcmemberhomerhuang3-Feb-10 16:41 
First,Thank you for your Excellent work.
When i trigged the MsgBox message(vb.net),I found the code excuted the WndProc function which is in the CustomCombobox class repeatedly and I couldn't close the MsgBox window, no matter Ok or Cancel button that I clicked.Please help me to solve this trouble,thanks!
GeneralRe: MsgBox message conflict with WndProcmemberlhayes004-Feb-10 6:15 
Hi,
 
I am glad that you found my article of interest!
 
Would you be able to provide an example of the problem that you are experiencing with some instructions that describe how I can reproduce the problem. I will then take a look into your specific problem.
 
I am familiar with VB.NET as well as C#, so it doesn't bother me which you use.
 
Many thanks,
Lea Hayes
GeneralDesigner improvement: SnapLinesmemberwolfgang_hg18-Nov-09 23:26 
Hi,
 
great piece of code!
 
One improvement: at design time, the "Snap lines" are missing. Here is an enhancement to the "CustomComboBoxDesigner" which adds at least the purple line used to align other controls in the some "row":
 
internal class CustomComboBoxDesigner : ParentControlDesigner
  {
    protected override void PreFilterProperties(IDictionary properties)
    {
      ...
    }
 
    public override IList SnapLines
    {
      get
      {
        IList snaplines = base.SnapLines;
 
        SnapLine snapBaseLine = new SnapLine(SnapLineType.Baseline, 15);
        snaplines.Add(snapBaseLine);
 
        return snaplines;
      }
    }
  }
 
I found that the Baseline for default comboboxes is at 15 pixel. Of course this does not work for non-default font sizes, but it is a good start Wink | ;-) .
 
Wolfgang
GeneralRe: Designer improvement: SnapLinesmemberlhayes0025-Nov-09 8:18 
Hi,
 
Thanks, I am glad that this has been of use!
 
I hadn't implemented any of the designer specific features because they were beyond the scope of the project that I was working on. Thank you for providing a code example for "Snap lines". I will try and include it in the next version.
 
Thanks again!
Lea Hayes
QuestionUse DroppedDown property instead of IsDroppedDown?memberT-C28-Oct-09 17:32 
Thanks for your code - very cool Smile | :)
 
My suggestion is to use the inherited DroppedDown property instead of the custom IsDroppedDown to minimize behavioral/interface changes to the inherited ComboBox. I have implemented this in my code, and so far it seems to work. Originally I attempted to set DroppedDown to false expecting it to work. Is there a reason I missed as to why you did not override DroppedDown?
 
Here is how I implemented DroppedDown:
 
[Browsable(false), Description("Gets or sets a value indicating whether the combo box is displaying its drop-down portion.")]
public new bool DroppedDown
{
    get { return m_bDroppedDown; }
    set 
    {
        if (value)
            ShowDropDown();
        else
            HideDropDown();
    }
}
 
In addition, I made ShowDropDown and HideDropDown private and non-virtual, deleted the IsDroppedDown property and changed IPopupControlHost as follows:
 
public interface IPopupControlHost
{
    #region Properties
 
    bool DroppedDown { get; set; }
 
    #endregion
}

 
Born to code.

AnswerRe: Use DroppedDown property instead of IsDroppedDown?memberlhayes0029-Oct-09 13:20 
Thank you for your kind words!
 
Without having an understanding of the underlying .NET code, I wanted to avoid causing problems elsewhere. I cannot remember if I tried overriding that property or not, it has been quite a while since I originally wrote this code.
 
I know that I explicitly reference the base.DroppedDown property within another function in that class to hide the original standard drop down, but despite this, I think there were some scenarios where the drop down was appearing above the custom drop down.
 
If overriding the DroppedDown property isn't causing any problems then I totally agree, this is a much neater approach. If this is the case, then personally I think that the ShowDropDown and HideDropDown functions should be protected and virtual to allow for specialized extensions.
 
Many thanks,
Lea Hayes
Questionset combo textmemberjixiaoliang26-Sep-09 17:48 
I create a numeric panel usercontrol, I want to ask how to get caller - combobox.text? Thanks
 
example: this.parent.text But,it's wrong. What should I?
AnswerRe: set combo textmemberlhayes0027-Sep-09 4:22 
The simplest way is to access the combobox control with its identifier. For example:
 
String text = myComboBox.Text;
 
Or, you could make some simple changes to your user control:
public class NumericPanel : UserControl
{
   ... YOUR STUFF ...
 
   public ComboBox OwnerDropDown { get; set; }
 
   public void testFunction()
   {
       if (OwnerDropDown != null)
       {
           String text = OwnerDropDown.Text;
       }
   }
}
And then add the following line to your construction code:
...
 
NumericPanel numericPanel = new NumericPanel();
numericPanel.OwnerDropDown = myComboBox;
 
...
Let me know how you get on!
 
Lea Hayes
Questionproperty ReadOnly [modified]membersiggi698-Sep-09 19:17 
Hi!
 
First I want to thank you for your work. It's a really nice and helpful control.
 
I just started programming in C#. Now I have a question:
There is no property to set the control read-only. If there is a chance to do so, would you please explain it?
 
Thank you very much!
 
siggi
 
modified on Wednesday, September 9, 2009 2:12 AM

AnswerRe: property ReadOnlymemberlhayes0011-Sep-09 2:32 
Try adding the following property into the "CustomComboBox" class, this should solve your problem.
 
The "DropDownStyle" attribute was only removed because the "Simple" mode is not compatible. Thanks for the feature suggestion, it will be included in the next update.
[Category("Custom Drop-Down")]
public bool ReadOnly
{
    get { return base.DropDownStyle == ComboBoxStyle.DropDown; }
    set { base.DropDownStyle = value ? ComboBoxStyle.DropDownList : ComboBoxStyle.DropDown; }
}
Let me know how you get on.
 
Lea Hayes
GeneralRe: property ReadOnlymemberlhayes0011-Sep-09 2:36 
Thinking about it, in read-only mode the control will probably not show any text because the "DropDownList" feature requires the original drop-down.
 
Adding one item to the list would solve this problem, but would cause two drop-downs to appear (one on top of the other).
 
Again, let me know how you get on.
GeneralControl.MinimumSizemembertonyt28-Aug-09 12:42 
Nice Work.
 
It would be nice if your resizable dropdown honored MinimumSize.
 
As it stands, the constraint is enforced, but your resize logic doesn't realize it.
 
Another useful feature would be the ability to add buttons to the resize bar at the bottom of the drop down, to have modal behavior (e.g., cancel and close, or accept and close).
GeneralRe: Control.MinimumSizememberlhayes0029-Aug-09 15:39 
Thank you very much for your suggestions.
 
I will try to incorporate the "MinimumSize" logic into the next update.
 
I am not sure about the idea of having a modal drop down because that is not the kind of behaviour a user would generally expect from a drop down control. In situations where a modal interface is required I would generally recommend using a dialog box perhaps with an ellipsis button: [TEXT BOX ][...]
 
Thanks again!
Lea Hayes
GeneralRe: Control.MinimumSizemembertonyt7-May-10 2:22 
In IE8, look at the search box drop down, for an example
of what I was referring by buttons (not necessarily modal
behavior).
GeneralDropDown ListViewmemberxnuks17-Aug-09 1:42 
How i implement the dropdowncontrol within listview control. Add coloumns, items, subitems
Questionautocompletemembercormoran29-Jul-09 5:19 
Dear All,
 
Can somebody tell me is it possible to enter some value into combobox, when dropdown form is loaded.
 
I should do this if I want to simulate autocomplete function.
 
The only way I found till now is to catch keydown event from popup form and to enter catched value into combobox.
 
If you open simple combobox in form you can see cursor and to write into combo when dropdown is open.
 
Thanks!
AnswerRe: autocompletememberlhayes007-Aug-09 12:33 
I do not understand what you are asking.
 
You can handle the KeyDown event whilst the user is typing in the actual combo box control. You can also handle the DropDown event which fires then the drop down form is shown, and then DropDownClosed is fired then the drop down form is hidden.
 
If you want to be able to type into the drop down form (and influence the combo control) then you will need to manually implement this into your specialized drop-down form.
 
I hope that this is of help, let me know if you have any further questions.
 
Many thanks,
Lea Hayes
GeneralParent form losing focus on hidememberPoustic17-Jul-09 5:36 
Hi - I'm trying to use your control with a TreeView, and much like a regular combobox I need to hide the dropdown when a node is selected. However calling HideDropDown() in my event handler causes the parent form to lose focus. Any way around this? Thx!
GeneralRe: Parent form losing focus on hidememberlhayes0017-Jul-09 8:24 
Perhaps something like the following would work?
myTreeCombo.HideDropDown();
myTreeCombo.Parent.Focus();
Let me know how you get on!
 
Many thanks,
Lea Hayes
GeneralRe: Parent form losing focus on hidememberPoustic17-Jul-09 9:05 
I tried various combinations without success... Here's the general idea:
 
private TreeView treeView1 = null;
 
private void Form1_Load(object sender, EventArgs e)
{
    treeView1 = new TreeView();
    treeView1.Nodes.Add("Node 1");
    treeView1.Nodes.Add("Node 2");
    treeView1.AfterSelect += new TreeViewEventHandler(treeView1_AfterSelect);
 
    customComboBox1.DropDownSizeMode = CustomComboBox.CustomComboBox.SizeMode.UseDropDownSize;
    customComboBox1.DropDownControl = treeView1;
}
 
void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    customComboBox1.HideDropDown();     // causes form to lose focus
    //customComboBox1.Parent.Focus(); 
}

GeneralRe: Parent form losing focus on hidememberlhayes0017-Jul-09 12:52 
Try the following, perhaps the re-focusing is being done too soon:
private TreeView treeView1 = null;
private Timer timerAutoFocus = null;
 
private void Form1_Load(object sender, EventArgs e)
{
    treeView1 = new TreeView();
    treeView1.Nodes.Add("Node 1");
    treeView1.Nodes.Add("Node 2");
    treeView1.AfterSelect += new TreeViewEventHandler(treeView1_AfterSelect);
 
    customComboBox1.DropDownSizeMode = CustomComboBox.CustomComboBox.SizeMode.UseDropDownSize;
    customComboBox1.DropDownControl = treeView1;
}
 
private void timerAutoFocus_Tick(object sender, EventArgs e)
{
    if (!this.Focused)
    {
        this.Focus();
        timerAutoFocus.Enabled = false;
    }
}
 
void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    customComboBox1.HideDropDown();     // causes form to lose focus

    // Re-focus main form...
    if (timerAutoFocus == null)
    {
        timerAutoFocus = new Timer();
        timerAutoFocus.Interval = 10;
        timerAutoFocus.Tick += new EventHandler(timerAutoFocus_Tick);
        timerAutoFocus.Enabled = true;
    }
}
 
I am unable to test the above code at this point, but I am pretty sure that something like this should do the trick.
 
Give it a try and let me know if it does the trick!
GeneralRe: Parent form losing focus on hidememberPoustic21-Jul-09 6:45 
Much better, thanks!
 
Only minor change is put timerAutoFocus.Enabled = true; outside the last if statement otherwise it only works once.
GeneralRe: Parent form losing focus on hidememberlhayes0021-Jul-09 7:31 
Excellent, I am glad that worked for you.
 
Well spotted, yeah that statement should have been beneath the if statement.
GeneralWrapping with toolstripmemberdebajyoti2005in8-Jul-09 23:21 
How to wrap this control with toolstrip
and when i try to use usercontrol then find when
RaiseDropDownEvent
RaiseDropDownClosedEvent invoked then it is not that much working.
GeneralRe: Wrapping with toolstripmemberlhayes009-Jul-09 0:46 
What are you trying to do?
 
a) Place this control on a tool strip?
b) Place a tool strip inside this control?
 
Can you please provide steps that I can follow to reproduce the problem relating to RaiseDropDownEvent and RaiseDropDownClosedEvent.
 
Possible tips:
 
- If you are trying to programatically show/hide the drop down part, then you should use the other two interfaces "ShowDropDown" and "HideDropDown".
- If you are trying to handle an event then you should attach an event handler to either "DropDown" or "DropDownClosed".
 
Many thanks,
Lea Hayes
GeneralDropDownClosed event not firingmemberdokmanov17-Jun-09 7:32 
How do you know when the user has/has not selected something?
GeneralRe: DropDownClosed event not firingmemberlhayes0017-Jun-09 9:27 
Thank you very much for your comment.
 
You are absolutely correct, the "DropDownClosed" event is not firing when the user clicks outside of the drop down. It does, however, fire when clicking the drop down arrow to close the popup. And it does fire when the popup is dynamically hidden.
 
I have made some changes to the control to fix this issue which I will upload to CodeProject soon. For the time being I have placed some instructions below. I think that this will address the problem that you mentioned above. Please make sure that you make a backup of your files prior to making the following changes:
 
#1 - Add the following code into the "PopupControl.cs" file:
 
    public interface IPopupControlHost
    {
        #region Methods
 
        /// <summary>
        /// Displays drop-down area of combo box, if not already shown.
        /// </summary>
        void ShowDropDown();
 
        /// <summary>
        /// Hides drop-down area of combo box, if shown.
        /// </summary>
        void HideDropDown();
 
        #endregion
    }
#2 - Update them_dropDown_Closed function of the PopupControl class in the "PopupControl.xs" file to match the following:
 
        private void m_dropDown_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            if (AutoResetWhenClosed)
                DisposeHost();
            
            // Hide drop down within popup control.
            if (PopupControlHost != null)
                PopupControlHost.HideDropDown();
        }
#3 - Change the "CustomComboBox" class declaration in the "CustomComboBox.cs" file to the following:
 
    public class CustomComboBox : ComboBox, IPopupControlHost
Please let me know how you get on with this!
 
Many thanks,
Lea Hayes
GeneralRe: DropDownClosed event not firingmemberdokmanov17-Jun-09 17:03 
I'm not a C# person and am getting a compile error on pt #2 of 3 above.
 
if (PopupControlHost != null)
PopupControlHost.HideDropDown();
 

What is "PopupControlHost?"
 
I don't see it defined anywhere.
 
I look fwd to updated code being posted.
 
Thanks!
GeneralRe: DropDownClosed event not firingmemberlhayes0019-Jun-09 3:13 
Ahh, sorry I forgot to mention, I have also added a new property to the "PopupControl" class in "PopupControl.cs".
 
Simply add the following directly beneath the "AutoResetWhenClosed" property (approx line 754):
        /// <summary>
        /// Gets or sets the popup control host, this is used to hide/show popup.
        /// </summary>
        public IPopupControlHost PopupControlHost { get; set; }
Give that a try and let me know if you have any more questions. Once you have confirmed that this fixes the problem that you were experiencing I will submit an update to CodeProject.
 
Thanks again,
Lea Hayes
GeneralRe: DropDownClosed event not firingmemberdokmanov19-Jun-09 3:52 
Well that elliminated the compile error but the event was still not raised.
 
I'd be happy to debug this for you but I don't know C#!
GeneralRe: DropDownClosed event not firingmemberlhayes0019-Jun-09 6:28 
Are you able to reproduce this problem with the example provided in the download on this article?
 
If so, could you please provide a detailed list of steps to reproduce?
 
i.e. The fix that I provided in the previous message solves the following problem on my system:
 
1. Click drop down arrow to open.
2. Click anywhere on form outside of drop down and drop down box.
3. Event is not raised (FIXED NOW)
 
1. Click drop down arrow to open.
2. Click drop down arrow to close.
3. Event is raised (NO CHANGES MADE)
 
Obviously this is an issue that I want to resolve.
 
Many thanks,
Lea Hayes
GeneralRe: DropDownClosed event not firingmemberdokmanov19-Jun-09 19:04 
I followed your instruction from scratch 3 times and still DropDownClose event does not fire when focus is lost.
GeneralRe: DropDownClosed event not firingmemberlhayes0019-Jun-09 21:40 
Hi,
 
Did you get my email? I sent you the ZIP file to your Yahoo account as you requested.
GeneralRe: DropDownClosed event not firingmemberdokmanov20-Jun-09 17:48 
Yep!
 
And it works now!
 

Very nice! Thank you!
GeneralRe: DropDownClosed event not firingmemberlhayes0021-Jun-09 2:31 
Excellent!
 
Thanks again for bringing this problem to my attention!
GeneralRe: DropDownClosed event not firingmemberlhayes0021-Jun-09 12:52 
The latest corrected version is now available from CodeProject.
 
Thanks again!
GeneralRe: DropDownClosed event not firingmemberdebajyoti2005in8-Jul-09 23:34 
i got an error Error 1 'CustomComboBox.PopupControl.PopupControlHost.get' must declare a body because it is not marked abstract or extern C:\WindowsApplication1\WindowsApplication1\PopupControl.cs 758 52 WindowsApplication1
what is the solve for this .
am using vs2005
GeneralRe: DropDownClosed event not firingmemberlhayes009-Jul-09 0:41 
Hi,
 
Are you using the latest version of this control? I have updated the version that is available from CodeProject now.
 
Can you please provide steps that I can follow to reproduce the error?
 
Many thanks,
Lea Hayes
QuestionUsing a ListBox?membermetator25-Apr-09 9:33 
Hi there,
 
First of all, i would like to say that i find this custom combobox really great and useful. But i think there's one thing it cannot do (or it seems really hard to do it). I'm trying to use this control to implement a real combobox using a listbox as the hosted control. What i want is to reutilize the size grip feature and, at the same time, maintain all the normal combobox functionality. So, in this scenario, hiding those "unwanted" properties will not help me at all. If i unhide them, the control might not be reusable in other scenarios. I'm also having trouble to mimic the combobox events - it doesn't fire when it is expected to.
 
My question is: is it possible to use your control in this scenario? Is there any other way where i can have a combobox dropdown with a size grip (using the DropdownList Style)? I know a normal combobox will only show a grip when using the AutoComplete feature, but i want to show the grip always.
 
Thanks in advanced.
 
You realize that everything you learn is in fact just learned, not necessarily true...

AnswerRe: Using a ListBox?memberlhayes0026-Apr-09 15:35 
Hi,
 
I am glad that you have found my combo box control useful!
 
One solution might be to create a new control with a name like "ListComboBox" which:
 
1. Constructs an instance of my combo box class, along with a list box.
2. Associates the list box with the combo box.
3. Provide access to the combo and list box properties that you need.
 
I have put together an example of how you might do this (see below). Simply put this in a file named "ListComboBox.cs". It works in much the same way as a regular list box, however it reacts more like a regular combo box. You will probably want to make some of your own alterations to this.
 
Thanks!
Lea Hayes
 

 
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
 
namespace CustomComboDemo
{
    public class ListComboBox : Control
    {
        #region Construction and destruction
 
        public ListComboBox()
        {
            List = new ListBox();
            
            Combo = new CustomComboBox.CustomComboBox(List);
            Combo.Dock = DockStyle.Fill;
            Controls.Add(Combo);
 
            List.SelectedIndexChanged += new EventHandler(List_SelectedIndexChanged);
            Combo.TextChanged += new EventHandler(Combo_TextChanged);
            Combo.KeyDown += new KeyEventHandler(ListComboBox_KeyDown);
        }
 
        #endregion
 
        #region Events
 
        void ListComboBox_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    if (List.SelectedIndex > 0)
                        --List.SelectedIndex;
                    break;
                case Keys.Down:
                    if (List.SelectedIndex + 1 < List.Items.Count)
                        ++List.SelectedIndex;
                    break;
                case Keys.Home:
                    List.SelectedIndex = List.Items.Count > 0 ? 0 : -1;
                    break;
                case Keys.End:
                    List.SelectedIndex = List.Items.Count - 1;
                    break;
            }
        }
 
        void List_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Adjust content of combo box text.
            Combo.Text = (List.SelectedItem != null) ? List.SelectedItem.ToString() : "";
            Combo.HideDropDown();
            Combo.Select();
        }
 
        void Combo_TextChanged(object sender, EventArgs e)
        {
            // Adjust selection within list control.
            List.SelectedIndex = List.FindStringExact(Combo.Text);
        }
 
        #endregion
 
        #region Combo Methods
 
        public void ShowDropDown()
        {
            Combo.ShowDropDown();
        }
 
        public void HideDropDown()
        {
            Combo.HideDropDown();
        }
 
        #endregion
 
        #region Combo Properties
 
        [Browsable(false)]
        public bool IsDroppedDown
        {
            get { return Combo.IsDroppedDown; }
        }
 
        [Category("Custom Drop-Down"), Description("Indicates if drop-down is resizable.")]
        public bool AllowResizeDropDown
        {
            get { return Combo.AllowResizeDropDown; }
            set { Combo.AllowResizeDropDown = value; }
        }
 
        [Category("Custom Drop-Down"), Description("Indicates current sizing mode."), DefaultValue(CustomComboBox.CustomComboBox.SizeMode.UseComboSize)]
        public CustomComboBox.CustomComboBox.SizeMode DropDownSizeMode
        {
            get { return Combo.DropDownSizeMode; }
            set { Combo.DropDownSizeMode = value; }
        }
 
        [Category("Custom Drop-Down")]
        public Size DropSize
        {
            get { return Combo.DropSize; }
            set { Combo.DropSize = value; }
        }
 
        [Category("Custom Drop-Down"), Browsable(false)]
        public Size ControlSize
        {
            get { return Combo.ControlSize; }
            set { Combo.ControlSize = value; }
        }
 
        #endregion
 
        #region List Events
 
        public event EventHandler DataSourceChanged
        {
            add { List.DataSourceChanged += value; }
            remove { List.DataSourceChanged -= value; }
        }
        public event EventHandler DisplayMemberChanged
        {
            add { List.DisplayMemberChanged += value; }
            remove { List.DisplayMemberChanged -= value; }
        }
        public event ListControlConvertEventHandler Format
        {
            add { List.Format += value; }
            remove { List.Format -= value; }
        }
 
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [Browsable(false)]
        public event EventHandler FormatInfoChanged
        {
            add { List.FormatInfoChanged += value; }
            remove { List.FormatInfoChanged -= value; }
        }
        public event EventHandler FormatStringChanged
        {
            add { List.FormatStringChanged += value; }
            remove { List.FormatStringChanged -= value; }
        }
        public event EventHandler FormattingEnabledChanged
        {
            add { List.FormattingEnabledChanged += value; }
            remove { List.FormattingEnabledChanged -= value; }
        }
        public event EventHandler SelectedValueChanged
        {
            add { List.SelectedValueChanged += value; }
            remove { List.SelectedValueChanged -= value; }
        }
        public event EventHandler ValueMemberChanged
        {
            add { List.ValueMemberChanged += value; }
            remove { List.ValueMemberChanged -= value; }
        }
 
        #endregion
 
        #region List Methods
 
        public string GetItemText(object item)
        {
            return List.GetItemText(item);
        }
 
        public void ClearSelected()
        {
            List.ClearSelected();
        }
 
        public int FindString(string s)
        {
            return List.FindString(s);
        }
 
        public int FindString(string s, int startIndex)
        {
            return List.FindString(s, startIndex);
        }
 
        public int FindStringExact(string s)
        {
            return List.FindStringExact(s);
        }
 
        public int FindStringExact(string s, int startIndex)
        {
            return FindStringExact(s, startIndex);
        }
 
        public int GetItemHeight(int index)
        {
            return List.GetItemHeight(index);
        }
 
        #endregion
 
        #region List Properties
 
        [AttributeProvider(typeof(IListSource))]
        [DefaultValue("")]
        [RefreshProperties(RefreshProperties.Repaint)]
        public object DataSource
        {
            get { return List.DataSource; }
            set { List.DataSource = value; }
        }
 
        [TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
        [DefaultValue("")]
        [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        public string DisplayMember
        {
            get { return List.DisplayMember; }
            set { List.DisplayMember = value; }
        }
 
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [Browsable(false)]
        [DefaultValue("")]
        public IFormatProvider FormatInfo
        {
            get { return List.FormatInfo; }
            set { List.FormatInfo = value; }
        }
 
        [MergableProperty(false)]
        [Editor("System.Windows.Forms.Design.FormatStringEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        [DefaultValue("")]
        public string FormatString
        {
            get { return List.FormatString; }
            set { List.FormatString = value; }
        }
 
        [DefaultValue(false)]
        public bool FormattingEnabled
        {
            get { return List.FormattingEnabled; }
            set { List.FormattingEnabled = value; }
        }
 
        public int SelectedIndex
        {
            get { return List.SelectedIndex; }
            set { List.SelectedIndex = value; }
        }
 
        [Browsable(false)]
        [DefaultValue("")]
        [Bindable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object SelectedValue
        {
            get { return List.SelectedValue; }
            set { List.SelectedValue = value; }
        }
 
        [DefaultValue("")]
        [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        public string ValueMember
        {
            get { return List.ValueMember; }
            set { List.ValueMember = value; }
        }
 
        [RefreshProperties(RefreshProperties.Repaint)]
        [DefaultValue(true)]
        [Localizable(true)]
        public bool IntegralHeight
        {
            get { return List.IntegralHeight; }
            set { List.IntegralHeight = value; }
        }
 
        [Localizable(true)]
        [RefreshProperties(RefreshProperties.Repaint)]
        [DefaultValue(13)]
        public int ItemHeight
        {
            get { return List.ItemHeight; }
            set { List.ItemHeight = value; }
        }
 
        [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Localizable(true)]
        [MergableProperty(false)]
        public ListBox.ObjectCollection Items
        {
            get { return List.Items; }
        }
 

        [DefaultValue(false)]
        public bool MultiColumn
        {
            get { return List.MultiColumn; }
            set { List.MultiColumn = value; }
        }
 
        [Localizable(true)]
        [DefaultValue(false)]
        public bool ScrollAlwaysVisible
        {
            get { return List.ScrollAlwaysVisible; }
            set { List.ScrollAlwaysVisible = value; }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public ListBox.SelectedIndexCollection SelectedIndices
        {
            get { return List.SelectedIndices; }
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Bindable(true)]
        public object SelectedItem
        {
            get { return List.SelectedItem; }
            set { List.SelectedItem = value; }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public ListBox.SelectedObjectCollection SelectedItems
        {
            get { return List.SelectedItems; }
        }
 
        public virtual SelectionMode SelectionMode
        {
            get { return List.SelectionMode; }
            set { List.SelectionMode = value; }
        }
 
        [DefaultValue(false)]
        public bool Sorted
        {
            get { return List.Sorted; }
            set { List.Sorted = value; }
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int TopIndex
        {
            get { return List.TopIndex; }
            set { List.TopIndex = value; }
        }
 
        [Browsable(false)]
        [DefaultValue(false)]
        public bool UseCustomTabOffsets
        {
            get { return List.UseCustomTabOffsets; }
            set { List.UseCustomTabOffsets = value; }
        }
 
        [DefaultValue(true)]
        public bool UseTabStops
        {
            get { return List.UseTabStops; }
            set { List.UseTabStops = value; }
        }
 
        #endregion
 
        #region Properties
 
        protected CustomComboBox.CustomComboBox Combo { get; private set; }
        protected ListBox List { get; private set; }
 
        #endregion
    }
}

GeneralRe: Using a ListBox?membermetator10-Jul-09 4:24 
Hi again,
 
Sorry for my late reply. I really like to thank for your help. I find this solution very elegant. You implemented through composition and my mistake was trying to do it through inheritance. This avoids having to unhide those unwanted properties. One minor suggestion: i was getting AccessViolationException when tring to set DropSize property (in designer generated code). I corrected this by changing the ListComboBox's parent class from Control to UserControl.
 
Best regards.
 
You realize that everything you learn is in fact just learned, not necessarily true...

GeneralRe: Using a ListBox?memberlhayes0010-Jul-09 14:55 
Hi,
 
No problem, I am glad that I was able to help you.
 
I will take a look into the AccessViolationException that you speak of.
 
Many thanks,
Lea Hayes
QuestionHow do I add this to my project pls?memberMember 197457016-Apr-09 3:15 
Hi
I am relatively new to this VS2005 and .Net winform development. Would you advice on how to add this control to my project for testing and possible customization please?!
 
TIA

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 21 Jun 2009
Article Copyright 2008 by Lea Hayes
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid