Click here to Skip to main content
15,867,141 members
Articles / Programming Languages / C#

ComboBox with Read Only Behavior

Rate me:
Please Sign up or sign in to vote.
4.66/5 (24 votes)
25 Apr 2005CPOL5 min read 398.4K   5K   63   54
An article about developing a ComboBox with the same read only functionality as the TextBox

Contents

Introduction

ReadReadOnly Behavior of the TextBox

TextBox controls have the nice read only feature. When you set the ReadOnly property of a TextBox to true, you can't edit the text in the TextBox anymore. The user can still select the text and copy it to another place. The background of the TextBox is painted gray so the user has a visual indication of the ReadOnly mode. The text is still painted in black, as in a normal editable TextBox.

This behavior is completely different to Enabled = false. Via the Enabled property, you can completely disable the TextBox. The text is not painted in good readable black anymore but in a gray color. And you can't select the text anymore.

Read only mode of TextBox

The ReadOnly mode is very usable. I often use it, when I have a form with several controls where the user can edit the content of controls depending on his privileges. If the user doesn't have the required privileges, I do not disable the controls but set them to ReadOnly. This way, the user can still very well read the texts in the TextBoxes, because their text is still painted in black.

No ReadOnly property for ComboBoxes

Most other .NET controls don't have a ReadOnly property. So if you want them to be read only, you have to disable them (Enabled = false). What I wanted was a ComboBox that offers a ReadOnly property and mimics the read only behavior of the TextBox. Especially, paint the text in good readable black instead of the disabled color gray.

DropDown Styles

Several people on the net argue, you don't need a ReadOnlyComboBox, because a ComboBox is read only when you set the DropDownStyle of the ComboBox to DropDownList. Well, of course, doing this, the user cannot edit the text in the ComboBox anymore. But he can still select a value from the ComboBox. For me, that's not the same thing as ReadOnly.

Solution

Idea

I tried different things like hooking into the WndProc to capture all the keyboard and mouse events and handle them myself, if the ComboBox is ReadOnly. But it just did not work out. I'm sure I did something wrong, but anyway. I'd also had to do the painting myself, where I had some problems as well.

Finally, I came up with a completely different idea. Whenever the ComboBox is set to ReadOnly = true, I display a TextBox instead that is read only. Because when it's read only, I don't need the dropdown button at all so a TextBox fits everything needed here.

Read only mode of ComboBox

Implementation

Basics

I found two implementation possibilities:

User Control Decorating the ComboBox and the TextBox

I could have created a new user control having a ComboBox and a TextBox at the same position. The user control acts as a decorator to the two embedded controls, and depending on the ReadOnly property, acts as a TextBox or a ComboBox.

I decided not to do that. Why should I do all the work to decorate the ComboBox? So I came up with solution two.

Inherit from ComboBox and Just Decorate the TextBox

I create a new control (ReadOnlyComboBox) that inherits from the standard ComboBox control and contains a TextBox. Whenever the ReadOnlyComboBox is set to read only, it acts as a decorator for the embedded TextBox and displays the TextBox instead of the ComboBox.

ReadOnly

First, I added a new property ReadOnly that handles the read only state.

C#
public bool ReadOnly
{
  get { return _isReadOnly; }
  set
  {
    if (value != _isReadOnly)
    { 
      _isReadOnly = value;

      ShowControl();
    }
  }
}

The ShowControl() method is responsible to show either the ComboBox or the TextBox depending on the ReadOnly and the Enabled properties.

C#
private void ShowControl()
{
  if (_isReadOnly)
  {
    _textbox.Visible = _visible && this.Enabled;
    base.Visible = _visible && !this.Enabled;
    _textbox.Text = this.Text;
  }
  else
  {
    _textbox.Visible = false;
    base.Visible = _visible;
  }
}

Visible

The ComboBox already has a Visible property. But we have to implement our own Visible property to store the control's visibility. The reason is simple: when we use the ReadOnly property, we change the visibility of the ComboBox. Thus the Visible property of the ComboBox does not correspond to the visibility of the ReadOnlyComboBox. That's why I declare a new Visible property that hides the original Visible property of the ComboBox.

C#
public new bool Visible
{
  get { return _visible; }
  set
  {
    _visible = value;
    ShowControl();
  }
}

But just replacing the Visible property is not enough. The two methods Show() and Hide() need to be replaced as well, to use our new Visible property.

C#
public new void Show()
{
  this.Visible = true;
}
  
public new void Hide()
{
  this.Visible = false;
}

Add the TextBox

While we have already used our TextBox, we have not yet created it. We'll do that in the constructor.

C#
public ReadOnlyComboBox()
{
  _textbox = new TextBox();
}

But that's not enough. We have to add the TextBox to the parent container and we have to copy several properties of the ComboBox to the TextBox. To add the TextBox, we override OnParentChanged() of the ComboBox.

C#
protected override void OnParentChanged(EventArgs e)
{
  base.OnParentChanged(e);
   
  if (Parent != null)
    AddTextbox();
  _textbox.Parent = this.Parent;
}
   
private void AddTextbox()
{
  _textbox.ReadOnly = true;
  _textbox.Location = this.Location;
  _textbox.Size = this.Size;
  _textbox.Dock = this.Dock;
  _textbox.Anchor = this.Anchor;
  _textbox.Enabled = this.Enabled;
  _textbox.Visible = this.Visible;
  _textbox.RightToLeft = this.RightToLeft;
  _textbox.Font = this.Font;
  _textbox.Text = this.Text;
  _textbox.TabStop = this.TabStop;
  _textbox.TabIndex = this.TabIndex;
}

Rest

In the AddTextbox() method, we make sure that the TextBox has the same behavior (like size, location, docking, anchor, etc.) like the ComboBox. But what if one of these properties changes during runtime? We have to make sure that such changes are propagated from the ComboBox to the TextBox. Therefore, I override several of the OnXXXX() methods of the ComboBox. Just a few of the overridden methods as example:

C#
protected override void OnSelectedIndexChanged(EventArgs e)
{
  base.OnSelectedIndexChanged(e);
  if (this.SelectedItem == null)
    _textbox.Clear();
  else
    _textbox.Text = this.SelectedItem.ToString();
}
  
protected override void OnEnabledChanged(EventArgs e)
{
  base.OnEnabledChanged(e);
  ShowControl();
}
  
protected override void OnDropDownStyleChanged(EventArgs e)
{
  base.OnDropDownStyleChanged(e);
  _textbox.Text = this.Text;
}
  
protected override void OnResize(EventArgs e)
{
  base.OnResize(e);
  _textbox.Size = this.Size;
}
  
protected override void OnLocationChanged(EventArgs e)
{
  base.OnLocationChanged(e);
  _textbox.Location = this.Location;
}

That's it. We finally have our ReadOnlyComboBox. In the same way, you could do a ReadOnlyDateTimePicker or a ReadOnlyNumericalUpDown and so on.

I will develop more read only enabled controls in the future. You'll find them here. Of course, if I have to implement one of them in a different way, I'll put it to Code Project again.

History

  • 03/28/2005: Initial version
  • 04/21/2005: First update
    • Added: Show() and Hide() methods because the Show() and Hide() methods of the parent ComboBox did not use our new Visible property but the Visible property of the parent control.
    • Bugfix: OnSelectedIndexChanged raised an exception when no item was selected (thanks to Alexandre Cunha for reporting this bug).
    • Bugfix: The TextBox is now added in the OnParentChanged() method. That solves several problems compared to the old solution where it was added in the ReadOnly property (thanks again to Alexandre Cunha for reporting one of these problems).
    • Changed: When the ComboBox was disabled, it showed a disabled ComboBox as it should be. When it was disabled and at the same time ReadOnly was true, it showed a disabled TextBox. When disabled, it now always shows a disabled ComboBox.

License

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


Written By
Team Leader
Switzerland Switzerland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
rmjcsltd20-May-20 11:12
rmjcsltd20-May-20 11:12 
GeneralMy vote of 5 Pin
Hesham Eraqi17-Sep-13 4:47
Hesham Eraqi17-Sep-13 4:47 
GeneralOne more problem solved - no more draging from Data Sources problems Pin
Tiago Freitas Leal19-Oct-09 13:19
professionalTiago Freitas Leal19-Oct-09 13:19 
AnswerRead Only mode's "Enter" event missing Pin
jasonhammertime2-Apr-08 4:21
jasonhammertime2-Apr-08 4:21 
GeneralIncompatible with layout panels Pin
Chuck_Esterbrook27-Dec-06 12:44
Chuck_Esterbrook27-Dec-06 12:44 
Generalprinting..... Pin
ssouki21-Jun-06 20:49
ssouki21-Jun-06 20:49 
GeneralKeyDown event handler Pin
Oskar Emil24-May-06 3:19
Oskar Emil24-May-06 3:19 
GeneralRe: KeyDown event handler Pin
Claudio Grazioli24-May-06 6:38
Claudio Grazioli24-May-06 6:38 
GeneralRe: KeyDown event handler Pin
Oskar Emil24-May-06 10:41
Oskar Emil24-May-06 10:41 
General[Dispose] method must be overriden... Pin
KSM31-Mar-06 1:10
KSM31-Mar-06 1:10 
GeneralUnable to update on dropdownlist style Pin
John Choo1-Mar-06 2:02
John Choo1-Mar-06 2:02 
GeneralWhy not... Pin
AlexSoh21-Dec-05 5:43
AlexSoh21-Dec-05 5:43 
GeneralRe: Why not... Pin
Claudio Grazioli21-Dec-05 6:31
Claudio Grazioli21-Dec-05 6:31 
GeneralRe: Why not... Pin
AlexSoh21-Dec-05 6:48
AlexSoh21-Dec-05 6:48 
GeneralProblems with data binding Pin
Anonymous29-Sep-05 10:21
Anonymous29-Sep-05 10:21 
GeneralRe: Problems with data binding Pin
Claudio Grazioli30-Sep-05 5:53
Claudio Grazioli30-Sep-05 5:53 
GeneralRe: Problems with data binding Pin
Nima Dilmaghani30-Sep-05 14:16
sussNima Dilmaghani30-Sep-05 14:16 
GeneralRe: Problems with data binding Pin
Member 1101459730-Apr-18 0:10
Member 1101459730-Apr-18 0:10 
GeneralSelectedItem does not work on OnSelectedIndexChanged Pin
Lalit Bhatia22-Sep-05 2:25
Lalit Bhatia22-Sep-05 2:25 
GeneralRe: SelectedItem does not work on OnSelectedIndexChanged Pin
Ilíon25-Aug-06 17:52
Ilíon25-Aug-06 17:52 
GeneralRe: SelectedItem does not work on OnSelectedIndexChanged Pin
csg120-Sep-06 11:23
csg120-Sep-06 11:23 
GeneralSame code for VB.NET Pin
ExplodingBoy19-Aug-05 7:09
ExplodingBoy19-Aug-05 7:09 
Questionhow to create a property like this Pin
isgrom3-Jul-05 18:10
isgrom3-Jul-05 18:10 
AnswerRe: how to create a property like this Pin
Anonymous4-Jul-05 7:09
Anonymous4-Jul-05 7:09 
GeneralRead only combobox with dropdown list Pin
Patric_J19-May-05 8:53
Patric_J19-May-05 8:53 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.