Click here to Skip to main content
Click here to Skip to main content

A listbox with disabled items

By , 2 Apr 2009
 

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:

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:

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.

//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:

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)

About the Author

Ron Levy
Software Developer
Israel Israel
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHi, Can it been used on WinCE or .netcf platform? Pinmemberwilliechen14 Nov '11 - 5:17 
GeneralList box font and leading... Pinmembermarketware8 Jan '10 - 5:54 
GeneralWhy not do this in a control PinmemberDonsw28 Apr '09 - 15:05 
GeneralMy vote of 1 PinmemberOrlandoCurioso9 Apr '09 - 2:03 
GeneralHorrible code PinmemberOrlandoCurioso3 Apr '09 - 4:41 
Earlier this year I spent extensive time with NET & Win32 Listbox, so I looked into your submission.
 
//If the selected item is a disabled item dont select it
How do you detect your disabled item, if you removed already prefix a few lines earlier?
And use outcommented SetSelected() to work in multiple selection mode too.
 
//Create the list of disabled items
No, you use a complete List to hold null or one disabled item.
 
Items[e.Index].ToString() / dt.Rows[e.Index][this.DisplayMember].ToString()
Use GetItemText(item) instead and retain standard formatting/database abilities.
 
Brush is a disposable object.
 
UseTabs ? / RightToLeft ?
Easy to implement with StringFormat. CustomTabs would be hard.
 
In your demo press Disable button twice to see a flaw in concept.
 
Instead of prefix, why not use a more familiar derived ListBox.IntegerCollection
that holds disabled items and dedicated GetDisabled, SetDisabled methods similiar to selected/checked items?
 
In future remove source control bindings from projects before publishing.
 
Sorry for my tone, but from a 'Team leader of a development team' I'd expect more.
(Spoiled my beautiful memories of Haifa)
 
Greetings
OrlandoCurioso
 
Try again. Fail again. Fail better. --- Samuel Beckett

GeneralRe: Horrible code PinmemberRon Levy4 Apr '09 - 20:54 
GeneralRe: Horrible code PinmemberOrlandoCurioso5 Apr '09 - 1:21 
Generalgreat idea PinmemberMember 47772992 Apr '09 - 3:33 

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

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 2 Apr 2009
Article Copyright 2009 by Ron Levy
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid