views:

255

answers:

2

This is a problem I've had to deal with in my last project, and although I found a working solution, I wasn't too happy with it and am wondering if there would've been a better, cleaner one.

Problem:

Basically, I needed to implement a ComboBox that inserts or appends an item (selected from the drop-down list) to the textbox instead of replacing all text in the textbox:

  • If the textbox has some text selected, that selection would be replaced with an item selected from the drop-down list;
  • If the textbox has no text selected, an item chosen from the drop-down list would be appended in the textbox field.

As it turned out, I could not achieve this behaviour by handling a combination of ComboBox's events (such as SelectedIndexChanged, SelectionChangeCommitted, TextChanged etc.) because the ComboBox control would finally synchronize the textbox field with the selected item from the drop-down list without raising any further events afterwards.

Solution, a.k.a ugly hack:

I ended up installing a Timer that, once expired, causes an update to the textbox field. The timer was set to approx. 30 ms, which should be long enough to ensure that all events (SelectedIndexChanged, TextUpdate etc.) have been processed, and short enough to not feel like a noticeable lag to the user.

Does anyone know of a cleaner solution to this problem?

+2  A: 

I'm sure you already know this, but I repeat it here to make you think consider the implications. A combo box is a relatively sophisticated control that is made of of simpler components interacting in a pre-defined way. A textbox, a list box and a button combine to create a control designed to simplify a common method of providing a compact UI for simplified text input and selection.

It seems your case does not lend itself to the pre-defined interactions of these components the way a combo box has designed them. Therefore my suggestion would be to separately create the textbox, listbox and button and manually define how they interact rather than trying to fight the pre-defined behavior of the combo box.

BlueMonkMN
Yes, that's a good solution. The reason I did not do it this way was that I wanted my control to look *exactly* like a regular combobox (which, considering Mark Byers' answer to this question, is actually not a good idea). However, this didn't seem possible because the drop-down button of a `ComboBox` does not look the same as a normal `Button`.
stakx
I also agree this may not be a good idea. But if you really did want your "custom control" to look just like a combobox, you could do the following. First, lay out on your form a textbox and a picturebox control to the right of it. Next, using a tool like SnagIt, screen-capture the two images in bitmap format for the up and down states of the built-in image of a combobox. Then, add the two bitmap files to a project resource file, and assign the captured images in the MouseUp and MouseDown events of the picturebox via [My Application Name].Properties.Resources.ResourceImageName
PaulR
I'm afraid this would be fairly difficult to implement correctly. The appearance of a combobox's drop-down button depends on the XP theme / colour style selected by the user. So it would not be enough to take a "screenshot" of that button beforehand, because the button might look different on another system. You'd have to dynamically create a bitmap of that button e.g. when the application starts, and every time that the user changes the Windows visual style.
stakx
In my opinion, it shouldn't look exactly like a combo box because it doesn't behave exactly like a combo box.
BlueMonkMN
+1  A: 

What you want is not a ComboBox. You want a text box and a button that when clicked gives you a drop down list of tokens which can be inserted into the text box. A ComboBox nearly gives you this but is unsuitable for two reasons:

  • Users known how ComboBoxes work. Your component looks like a ComboBox but doesn't behave like one. That will just cause confusion.
  • ComboBoxes are designed in the way they are so that users will always know how they work and can be familiar with them. It is not the intention that the selected item differs from the text. You can't override this behaviour because if you did, it would no longer be a ComboBox as we know it. Trying to override it to completely change the behavior of the control in a way for which it was not designed causes problems that are not easy to fix.

You should write a custom control which implements the features you need and has a UI that better represents what you are doing. To look for inspiration you could consider the 'insert emoticon' UI that many instant messaging programs have. Notice that the button is not typically inside the text box but a completely separate button.

Mark Byers