Introduction
The standard ComboBox
really does need a .ReadOnly
property. I've been using a kludge to emulate read-only behavior -- positioning both a ComboBox
and a TextBox
of equal sizes on my form(s) and setting one or the other as .Visible
depending on the "mode" at the moment.
Recently, reading this article sparked ideas on how to achieve the goal of ComboBox
with a .ReadOnly
property that works the way I'd expect. The result of my effort is presented here as: TdhComboBox
.
The demo example compares three standard ComboBox
es (one each with .DropDownStyle
property set to 'DropDown
,' 'DropDownList
' and 'Simple
') to three corresponding instances of TdhComboBox
. In the screen-shot, the standard ComboBox
es are disabled and the TdhComboBox
es are read-only.
Using the Control
To use TdhComboBox
as is, add a reference in your project to the class library 'TDHComboBox.dll.' The namespace used in this library is:
using TDHControls.TDHComboBox;
The TdhComboBox
control was written (and compiled) using VS2002 (.NET 1.0) with the intention that the source code be readily available to other developers regardless of the .NET version they are using.
The novel members of TdhComboBox
's interface are:
Colors_Set()
- The method sets the control's .BackColor
and .ForeColor
as appropriate to its current state. The developer shouldn't need to call this method; the main reason for writing it was to have a single section of code to perform this function (and, since the method exists, I decided to expose it).
Text_Set()
- The method's signature is: [public bool Text_Set(string setValue, bool forceIfEmptyString)
]. This method allows the developer to programatically select an .Item
from the control's Items collection -- that is, it may trigger the control's SelectedIndexChanged
Event. If the value of 'setValue
' is not a member of the Items collection, the control's .Text
property will nevertheless be set to the value of 'setValue
' under the following conditions: 1) the control's .DropDownStyle
property is not set to 'DropDownList
,' or 2) the value of 'setValue.Trim()
' is an empty string and the value of 'forceIfEmptyString
' is 'true.' The method's return value reflects whether the value of the .Text
property was successfully set.
ReadOnly
- This boolean
property determines whether the control is in read-only mode.
ReadOnlyAllowDrop
- This boolean
property determines whether the DropList may be opened when the control is in read-only mode.
AllowTextCut
- When the control's .DropDownStyle
property is set to 'DropDownList
,' this boolean
property allows the user to use the ContextMenu to 'Cut' or 'Delete' the value of the .Text
property or 'Paste' a white-space string object to the .Text
property -- even if the .Items
collection doesn't contain a empty string or white-space string object.
ContextMenuEnabled
- This boolean
property determines whether the control's ContextMenu
is enabled/available. Upon initialization, the TdhComboBox
instance builds its own ContextMenu
, or the developer may supply one by setting the standard .ContextMenu
property.
It should go without saying that the "disabled" colors take precedence over any of the Color
properties described below:
DropDownListBackColor
- This Color
property determines the background color to be used when the control's .DropDownStyle
property is set to 'DropDownList
' (and the control is not in read-only mode).
DropDownListForeColor
- This Color
property determines the foreground color to be used when the control's .DropDownStyle
property is set to 'DropDownList
' (and the control is not in read-only mode).
NormalBackColor
- This Color
property determines the background color to be used normally -- that is, when the control's .DropDownStyle
property is not set to 'DropDownList
' and the control is not in read-only mode.
NormalForeColor
- This Color
property determines the foreground color to be used normally -- that is, when the control's .DropDownStyle
property is not set to 'DropDownList
' and the control is not in read-only mode.
ReadOnlyBackColor
- This Color
property determines the background color to be used when the control is in read-only mode. This property takes precedence over the .DropDownListBackColor
and .NormalBackColor
properties.
ReadOnlyForeColor
- This Color
property determines the foreground color to be used when the control is in read-only mode. This property takes precedence over the .DropDownListForeColor
and .NormalForeColor
properties.
Modified (overridden) members of TdhComboBox
's interface are:
BackColor
- The .BackColor
property has not been explicitly overridden; however, the novel Color
properties described above take precedence and may over-write values to which this property is set.
ForeColor
- The .ForeColor
property has not been explicitly overridden; however, the novel Color
properties described above take precedence and may over-write values to which this property is set.
DrawMode
- This property's default value is now 'OwnerDrawFixed
' and the 'Normal
' enumeration-value is not selectable. The control doesn't contain any code to specificly deal with 'OwnerDrawVariable
' (so, it's probably best to stick with 'OwnerDrawFixed
').
Other than the code for these properties, TdhComboBox
is intended to behave as a standard ComboBox
-- though, of course, I won't guarantee that it does.
Known Issues
- In the
OnDrawItem()
method, when the .DataSource
property is set (as opposed to an Items Collection
having been generated via the .Items.Add()
method), the section of code which determines the string value of the item being drawn *assumes* the item object can be cast to a System.Data.DataRowView
object.
- 2006 October 12: Version 1.0.004 corrects this issue.
- When
(.DropDownStyle == Simple)
, highlighting items in the "drop down list" as the mouse cursor passes over them is yet imperfect. Specifically, when the cursor moves back into the "virtual ClientRectangle" (which my code computes), I force an .Invalidate()
in case the user's last action was to use the control's ScrollBar. The .Invalidate()
causes the ScrollBar to return correct values (this is good), but it also triggers a Paint Event
, which may actually happen *after* my code has drawn/highlighted the item (thus causing the highlighting to vanish).
- When the control is used in a .NET 1.1 application, the mouse cursor may be used to select text (by clicking-and-dragging) in the EditBox portion of the ComboBox. When the control is used in a .NET 1.0 application, this doesn't seem to be an option. The interesting thing, to me at any rate, is that in both cases the DLL was compiled under .NET 1.0.
Wish List
- Improve the code in the
OnDrawItem()
method dealing with the .DataSource
property.
- Resolved with Version 1.0.004
- Come up with a way to hide the "drop-arrow" when the control is in
ReadOnly
mode and the .ReadOnlyAllowDrop
property is false.
- Resolved with Version 1.0.004
- Enable the ContextMenu to copy specific entries/items from the control's DropList to the Windows clipboard.
- Devise a resolution for the problem of highlighted items in the "drop down list" when
(.DropDownStyle == Simple)
.
History
- 2006 August 18: Submission of
TdhComboBox
ver 1.0.001 to The Code Project.
- 2006 August 25: Version 1.0.002 - Added
.AllowTextCut
and .ReadOnlyAllowDrop
properties and Colors_Set()
and Text_Set(string setValue, bool forceIfEmptyString)
methods.
- 2006 October 12: Version 1.0.004
- In the
OnDrawItem()
overridden method, use the base ComboBox .GetItemText()
method to get the text value of the .Item
being drawn. This corrects a know issue. [Thanks to Alan Brookland for this suggestion]
- Added logic to over-paint (hide) the "drop-arrow" when ['
this.ReadOnly
' and '!this.ReadOnlyAllowDrop
'].