Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / Windows Forms

A listbox with disabled items

Rate me:
Please Sign up or sign in to vote.
3.81/5 (12 votes)
2 Apr 2009CPOL2 min read 69.1K   2.3K   27   8
A custom listbox control with disabled list items.

Introduction

This is a listbox User Control with an option for disabled items. The disabled item can be marked as disabled with a prefix that you choose, or by choosing a boolean column in the source database for the list DataSource.

Background

I had some projects that I needed a listbox to display disabled item. The ListBox that comes with VS does not expose this attribute for the listbox items. I ended up writing my own User Control with the ability to mark some items as disabled. This is great if you have an application that uses a database and has many users that update the data, and you want to mark an object as disabled if you can't use it any more, or if say, some one else is working on the same object at that time.

Using the code

The base for this solution is using the DrawMode.OwnerDrawFixed attribute in the ListBox control. We need to start by creating a UserControl project and inherit from ListBox. Then, just add the following line inside the constructor of the control:

C#
this.DrawMode = DrawMode.OwnerDrawFixed; 

This means that we control how the listbox is drawn.

Next, we need to override the method OnDrawItem(DrawItemEventArgs e). This method does the drawing of the items inside the listbox control. Here, we choose if we want to draw the item as disabled or not.

This is the code for a disabled item base using a prefix for disabled items:

C#
string item = this.Items[e.Index].ToString();
//Check if the item is disabled
if (item.StartsWith(prefix))
{
    item = item.Remove(0, prefix.Length);
    myBrush = Brushes.Gray;
}
if (!item.StartsWith(prefix))
{
    // Draw the background of the ListBox control for each item.
    e.DrawBackground();
}
// Draw the current item text based on the current Font and the custom brush settings.
e.Graphics.DrawString(item, e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);

Next, we want to enable selecting an item.

C#
//If the selected item is a disabled item dont select it
if ((e.State & DrawItemState.Selected) == 
     DrawItemState.Selected && item.StartsWith(prefix))
{
    this.SelectedIndex = -1; 
    this.Invalidate();
}
//if the selected item is not disable change the text color to white
else if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
    myBrush = Brushes.White;
    e.Graphics.DrawString(item, e.Font, myBrush, e.Bounds, 
                          StringFormat.GenericDefault);
    e.DrawFocusRectangle();
}
else
{
    if (!item.StartsWith(prefix))
        // If the ListBox has focus, draw a focus
        // rectangle around the selected item.
        e.DrawFocusRectangle();
}

Now, we must draw the item back into the listbox control:

C#
base.OnDrawItem(e);

In the attached source code, you will find the code for connecting the disabled items to a column in a database.

That's it. Enjoy!

Points of interest

It is always fun to play with the built-in controls. Remember, you can do any thing you want (almost) in VS.

License

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


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

Comments and Discussions

 
QuestionHi, Can it been used on WinCE or .netcf platform? Pin
williechen14-Nov-11 5:17
williechen14-Nov-11 5:17 
GeneralList box font and leading... Pin
marketware8-Jan-10 5:54
marketware8-Jan-10 5:54 
GeneralWhy not do this in a control Pin
Donsw28-Apr-09 15:05
Donsw28-Apr-09 15:05 
GeneralMy vote of 1 Pin
OrlandoCurioso9-Apr-09 2:03
OrlandoCurioso9-Apr-09 2:03 
GeneralHorrible code Pin
OrlandoCurioso3-Apr-09 4:41
OrlandoCurioso3-Apr-09 4:41 
GeneralRe: Horrible code Pin
Ron Levy4-Apr-09 20:54
Ron Levy4-Apr-09 20:54 
GeneralRe: Horrible code Pin
OrlandoCurioso5-Apr-09 1:21
OrlandoCurioso5-Apr-09 1:21 
Hi Ron,
I understand that bugs in non DB part don't bother you, as your solution seems to work
for your specific requirement. Machine is big enough and application runs short time,
so you get away without 'Out of Resources' exception, while happily creating new brushes
on every item repaint.

Either use basic IDisposable pattern:

using(Brush brush = SolidBrush(isDisabledItem ? SystemColors.GrayText: e.ForeColor))
{ // DrawItemEventArgs provides correct colors, unless listbox or item is disabled }

or use System.Drawing.SystemBrushes.WindowText/.Window etc since
SystemBrush should not be disposed and your current code may be easily updated.

BTW Brushes.Black/.White may not produce correct system colors (theming).

string text = GetItemText(Items[e.Index]);
Look at ListControl.GetItemText method from Reference Source or Reflector and you will
see it handles item text, in all scenarios you never thought of.

'demo is just a demo', sure who would expect a functioning demo?

OrlandoCurioso

Try again. Fail again. Fail better. --- Samuel Beckett

Generalgreat idea Pin
Member 47772992-Apr-09 3:33
Member 47772992-Apr-09 3:33 

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.