.NET Forum / Languages / C# / July 2007
Changing the font in a listbox
|
|
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 MagazinesGet 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 ...
|
|
|