Introduction
One of the things I have never liked about the combobox
is that it is almost unreadable when it is disabled. I have an application that does a lot of databinding and enables or disables controls behind the scenes based upon access rules. The combobox
es show the right values, but it is grey on beige, and very hard to read. I don't want to make them textbox
es because it would make my code considerably more complex (the GUI is generated at runtime).
I did a lot of research on the web and didn't find too many articles that dealt specifically with changing the appearance of the edit box. There are lots of articles that show an ownerdrawn
list, but that only is helpful when the listbox
is enabled.
What It Looks Like
As you can see in the first entry, the disabled combo is pretty ugly. The second entry shows my control in a disabled state - much more readable! The third entry shows that the control works normally when enabled.
I implemented the code as a simple subclass from combobox
, so it can be dropped in as a replacement anywhere a combobox
is used.
Key Parts of the Code
First, to allow your combo to be owner drawn, you have to add a DrawItemEventHandler
and also set the DrawMode
to OwnerDrawFixed
. You can use OwnerDrawVariable
if you want to change the size of the list, but I am not doing that here. I also added a handler for EnabledChanged
event.
this.DrawItem += new DrawItemEventHandler(EnableDisplayCombo_DrawItem);
this.DrawMode = DrawMode.OwnerDrawFixed;
this.EnabledChanged += new EventHandler(EnableDisplayCombo_EnabledChanged);
Next, in the EnabledChanged
event, I change the DropDownStyle
based upon whether the control is enabled or not. A DropDownStyle
of just DropDown
will allow the control to be typed into, but DropDownList
will only allow the use of the mouse. The catch is that you can only control the appearance of the EditBox
if you set the DropDownStyle
to DropDownList
. For a disabled control, it doesn't matter since you can't select it anyway.
void EnableDisplayCombo_EnabledChanged(object sender, EventArgs e)
{
if (this.Enabled)
this.DropDownStyle = ComboBoxStyle.DropDown;
else
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
Finally, here is the ownerdraw
routine. Basically, you just key on the state of the item that needs to be drawn, and draw it however you want.
void EnableDisplayCombo_DrawItem(object sender, DrawItemEventArgs e)
{
System.Drawing.Graphics g = e.Graphics;
Rectangle r = e.Bounds;
if (e.Index >= 0)
{
string label = this.Items[e.Index].ToString();
if (e.State == (DrawItemState.Disabled | DrawItemState.NoAccelerator
| DrawItemState.NoFocusRect | DrawItemState.ComboBoxEdit))
{
e.Graphics.FillRectangle(new SolidBrush(Color.White), r);
g.DrawString(label, e.Font, Brushes.Black, r);
e.DrawFocusRectangle();
}
else if (e.State == (DrawItemState.NoAccelerator |
DrawItemState.NoFocusRect))
{
e.Graphics.FillRectangle(new SolidBrush(Color.White), r);
g.DrawString(label, e.Font, Brushes.Black, r);
e.DrawFocusRectangle();
}
else
{
e.Graphics.FillRectangle(new SolidBrush(Color.Blue), r);
g.DrawString(label, e.Font, Brushes.White, r);
e.DrawFocusRectangle();
}
}
g.Dispose();
}
Note that if you use databinding
, you will have to use a little more complex code in the line where the label is assigned. Maybe something like this:
string label = Convert.ToString(item[this.DisplayMember]);
I hope this is useful to somebody. The solution is pretty simple, but it took me a long time to piece it together from various sources. Any comments or suggestions are very welcome.
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.