Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

TdhComboBox - An Inherited ComboBox With ReadOnly Property

3.11/5 (13 votes)
12 Oct 2006CPOL6 min read 1   689  
This article describes a subclassed ComboBox with ReadOnly functionality.

Sample Image - TdhComboBox.gif

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 ComboBoxes (one each with .DropDownStyle property set to 'DropDown,' 'DropDownList' and 'Simple') to three corresponding instances of TdhComboBox. In the screen-shot, the standard ComboBoxes are disabled and the TdhComboBoxes 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:

C#
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'].

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)