Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / July 2007

Tip: Looking for answers? Try searching our database.

Changing the font in a listbox

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Dom - 27 Jul 2007 20:44 GMT
In some programs, I see that certain items in a listbox have been
grayed, to indicate that they are "there" but can not be chosen.  This
is very helpful.  Can you do this in CSharp?  Is there a
lstMain.SelectedItem.Enabled?

Dom
Morten Wennevik [C# MVP] - 27 Jul 2007 20:57 GMT
> In some programs, I see that certain items in a listbox have been
> grayed, to indicate that they are "there" but can not be chosen.  This
> is very helpful.  Can you do this in CSharp?  Is there a
> lstMain.SelectedItem.Enabled?
>
> Dom

No, but you can make it appear non selectable by ownerdrawing the ListBox.

[pseudocode]
OnDrawItem(DrawItemEventArgs e)
{
    MyObject o = (MyObject)listMain.Items[e.Index];
    if( o.NotSelectable )
        // DrawGrayedOut
    else
        // DrawNormal
}

Signature

Happy coding!
Morten Wennevik [C# MVP]

Dom - 27 Jul 2007 21:33 GMT
On Jul 27, 3:57 pm, "Morten Wennevik [C# MVP]"
<MortenWenne...@hotmail.com> wrote:
> > In some programs, I see that certain items in a listbox have been
> > grayed, to indicate that they are "there" but can not be chosen.  This
[quoted text clipped - 19 lines]
> Happy coding!
> Morten Wennevik [C# MVP]

This led me to something in the help files.  Thanks.  Before I get
started, how do I trigger the OnDrawItem?  Let me give you a fuller
picture.

I have two listboxes, side by side.  One is the "Not included" list,
and the other is the "Included" list.  The user can move an item back
and forth between these listboxes by buttons.  After an item moves
from the "Not included" list to the "included list", I want it to
appear grayed out, indicating that it is already used up.

So I guess I have to get the button to trigger the OnDrawItem event.
How is that done?

Dom
Peter Duniho - 27 Jul 2007 21:55 GMT
> I have two listboxes, side by side.  One is the "Not included" list,
> and the other is the "Included" list.  The user can move an item back
[quoted text clipped - 4 lines]
> So I guess I have to get the button to trigger the OnDrawItem event.
> How is that done?

The easiest way is to simply invalidate the entire control.  See the
Invalidate() method.  OnDrawItem is a method, not an event, and it gets
called when the control needs to be redrawn, in response to invalidation
of the control.

Personally, as a UI paradigm I think it's better to remove the items
altogether rather than disabling them.  This fits better with the "move"
 paradigm that you seem to be using already.  And as an added benefit,
implementing that would be a LOT easier than dealing with disabling the
list items (I've done the former myself, and it's only 20-30 lines of
code, none of them nearly as tricky as overriding basic Window message
event logic in the control).

Pete
Dom - 27 Jul 2007 22:16 GMT
> > I have two listboxes, side by side.  One is the "Not included" list,
> > and the other is the "Included" list.  The user can move an item back
[quoted text clipped - 19 lines]
>
> Pete

Yes, I'm starting to think it is better just to remove the item.  It's
a shame though, we really should be easy to do
"lstMain.SelectedItem.Enabled = false".
Morten Wennevik [C# MVP] - 27 Jul 2007 21:58 GMT
> On Jul 27, 3:57 pm, "Morten Wennevik [C# MVP]"
> <MortenWenne...@hotmail.com> wrote:
[quoted text clipped - 36 lines]
>
> Dom

OnDrawItem is enabled when you set DrawMode to either of the OwnerDraw modes (OwnerDrawFixed is what you need here).  In addition you need to subscribe to the ListBox' DrawItem event.  The code below demonstrates the principles.  You can still select the item, though, but it won't appear selected.  To simulate an item that should be disabled I used three string items "one", "two", and "three" and item "two" appears with gray background and text.

protected override void OnLoad(EventArgs e)
{
    listBox1.DrawMode = DrawMode.OwnerDrawFixed;
    listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);
}

void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    if (listBox1.Items[e.Index].ToString() == "Two")
    {
        e.Graphics.FillRectangle(Brushes.Gray, e.Bounds);
        e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), listBox1.Font, SystemBrushes.InactiveCaptionText, e.Bounds);
    }
    else
    {
        e.DrawBackground();
        if ((e.State & DrawItemState.Focus) > 0)
            e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), listBox1.Font, SystemBrushes.HighlightText, e.Bounds);
        else
            e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), listBox1.Font, SystemBrushes.ControlText, e.Bounds);
    }
}

Signature

Happy coding!
Morten Wennevik [C# MVP]

Peter Duniho - 27 Jul 2007 21:06 GMT
> In some programs, I see that certain items in a listbox have been
> grayed, to indicate that they are "there" but can not be chosen.  This
> is very helpful.  Can you do this in CSharp?  Is there a
> lstMain.SelectedItem.Enabled?

I don't believe that the ListBox class supports this directly.  I
haven't tried this, but I think you might be able to do it yourself by
deriving a new class from ListBox and in that class:

    * Keep your own list of disabled items.

    * Override OnDrawItem, and when drawing a disabled item, change the
font color before calling the base.OnDrawItem() method and then
restoring the font color to what it was before.

    * Override WndProc, and before allowing a mouse click to be passed
to the base.WndProc() method, use the IndexFromPoint() method to
determine the item being clicked, and don't call the base.WndProc()
method if it's a disabled item.

    * Override ProcessDialogKey, and just as you intercept mouse
events, intercept the keyboard events that might select a disabled item,
and do something to prevent that (IMHO the most user-friendly way would
be to repeat the keyboard events as necessary to skip over disabled
items, but there are a variety of ways you could choose to do this).

That's the general idea...I may have missed some specifics, or it may
turn out that there are better ways to do some of the above.  As you can
see, it would be non-trivial to implement the behavior you want, but it
is probably less difficult to do that than to write a whole new listbox
class that does what you want.  :)

Pete
Dom - 28 Jul 2007 04:36 GMT
> In some programs, I see that certain items in a listbox have been
> grayed, to indicate that they are "there" but can not be chosen.  This
> is very helpful.  Can you do this in CSharp?  Is there a
> lstMain.SelectedItem.Enabled?
>
> Dom

Actually, guys, it turned out to be very simple.  Here's what I did:

private void btnSelect_Click(object sender, EventArgs e)
{
 ((ListItem)lstMain.SelectedItem).IsSelected = true;
 lstMain.Invalidate();
}

private void lstMain_DrawItem(object sender, DrawItemEventArgs e)
{
 if (e.Index < 0) return;
 e.DrawBackground();
 Brush myBrush = ((ListItem)lstMain.Items[e.Index]).IsSelected ?
Brushes.Gray : Brushes.Black;

 e.Graphics.DrawString(lstMain.Items[e.Index].ToString(),
     e.Font, myBrush,
     e.Bounds,
     StringFormat.GenericDefault);
 e.DrawFocusRectangle();
}

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.