Listbox Objects that are not strings!

Merchand

Well-known member
Joined
Dec 28, 2005
Messages
73
Location
USA Eastcoast
Programming Experience
10+
I'm trying to add a multiline textbox to a listbox control.

My main objective is to add a multiline error message to a listbox item.

How do you add a textbox to the listbox items collection and be able to view it and the data stored in the .text property of the textbox?

Any help is greatly appreciated!!! :)
 
:confused: I have added just the text, but I'm wanting to have several lines per item...
Example...

Time: 4PM 02Feb2006
Module: MyModule
App: MyApp
Error: Error Text here.
<space>

next message...

I have tried adding vbCrLf in a StringBuilder object then add the sb.ToString() to the lstError.Item.Add(sb.ToString).

It is not taking my vbCrlfs :confused:
 
Oh, ya... this code is in VS2003 (FW1.1). I'm using both but only 2005 at home.
 
VB.NET:
[SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].TextBox1.Text = "Text item: 1" & ControlChars.NewLine
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].TextBox1.Text &= "Text item: 2" & ControlChars.NewLine
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].TextBox1.Text &= "Text item: 3" & ControlChars.NewLine
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].TextBox1.Text &= "Text item: 4"[/SIZE]
 
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] myArray() [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2] = [/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].TextBox1.Text.Split(ControlChars.NewLine)
[/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2] i [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE][SIZE=2] = 0 [/SIZE][SIZE=2][COLOR=#0000ff]To[/COLOR][/SIZE][SIZE=2] myArray.GetUpperBound(0)
[/SIZE][SIZE=2][COLOR=#0000ff]   Me[/COLOR][/SIZE][SIZE=2].ListBox1.Items.Add(myArray(i).Trim)
[/SIZE][SIZE=2][COLOR=#0000ff]Next[/COLOR][/SIZE]

HTH
Regards ;)
 

Attachments

  • MultilinetextBoxToListBox.zip
    22.3 KB · Views: 74
That's what I thought too... but doesn't that then add each line as it's own item? I'm not sure that a listbox can display multilined items.... would almost be easier at this point to create your own control that does what you need it to.... Hmmm.....

Or inherit the listbox and do an ownerdraw deal on it to display what you need. Not sure how to do that though.

-tg
 
HTH/TG:

I read both of you! I really don't want to add four items to my listbox collection just one item what is multiline.

I'd even go for columns at this point but I have not seen any good examples of showing columns either. I know how to use the listview control in VB6 and know I can do it in .net but just seems like this listbox control in vs2003 is very limited.

Since, this listbox control can hold any type of object I thought I could just add the textbox to the .Add() method but that seems to just add a text representation of it.

I believe there are no good examples on how to inherit and/or overload this control. (???)

Has anyone ever added a different control to the listbox? I thought I saw this done a few years ago with a picturebox control. [???]

DotNet has made me feel real stupid lately! :confused:
 
You even don't have to inherit the ListBox control.
Set the DrawMode property to OwnerDrawVariable, implement the MeasureItem and DrawItem event handlers and draw the text yourself.

Example (.NET 2.0) :
VB.NET:
[COLOR=#0000ff]Private[/COLOR] [COLOR=#0000ff]Sub[/COLOR] ListBoxErrorsDrawItem([COLOR=#0000ff]ByVal[/COLOR] sender [COLOR=#0000ff]As[/COLOR] System.Object, _
[COLOR=#0000ff]ByVal[/COLOR] e [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.DrawItemEventArgs) [COLOR=#0000ff]Handles[/COLOR] ListBoxErrors.DrawItem
[COLOR=#0000ff]   Dim[/COLOR] lb [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.ListBox = [COLOR=#0000ff]DirectCast[/COLOR](sender, ListBox)
    [COLOR=#0000ff]Dim[/COLOR] item [COLOR=#0000ff]As[/COLOR] MyError = [COLOR=#0000ff]DirectCast[/COLOR](lb.Items(e.Index), MyError)
    e.DrawBackground()
    [COLOR=#0000ff]If[/COLOR] (e.State [COLOR=#0000ff]And[/COLOR] DrawItemState.Selected) = 0 [COLOR=#0000ff]Then[/COLOR]
        [COLOR=#0000ff]If[/COLOR] e.Index [COLOR=#0000ff]Mod[/COLOR] 2 = 0 [COLOR=#0000ff]Then[/COLOR]
            e.Graphics.FillRectangle(Brushes.Beige, e.Bounds)
        [COLOR=#0000ff]Else[/COLOR]
            e.Graphics.FillRectangle(Brushes.BlanchedAlmond, e.Bounds)
        [COLOR=#0000ff]End[/COLOR] [COLOR=#0000ff]If[/COLOR]
    [COLOR=#0000ff]End[/COLOR] [COLOR=#0000ff]If[/COLOR]
    e.Graphics.DrawRectangle(Pens.Silver, e.Bounds)
    TextRenderer.DrawText(e.Graphics, item.Text, lb.Font, e.Bounds, e.ForeColor, TextFormatFlags.Default)
    [COLOR=#0000ff]If[/COLOR] (e.State [COLOR=#0000ff]And[/COLOR] DrawItemState.Selected) <> 0 [COLOR=#0000ff]Then[/COLOR] e.DrawFocusRectangle()
[COLOR=#0000ff]End[/COLOR] [COLOR=#0000ff]Sub[/COLOR]
 
 
[COLOR=#0000ff]Private[/COLOR] [COLOR=#0000ff]Sub[/COLOR] ListBoxErrorsMeasureItem([COLOR=#0000ff]ByVal[/COLOR] sender [COLOR=#0000ff]As[/COLOR] System.Object, [COLOR=#0000ff]_
ByVal[/COLOR] e [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.MeasureItemEventArgs) [COLOR=#0000ff]Handles[/COLOR] ListBoxErrors.MeasureItem
    [COLOR=#0000ff]Dim[/COLOR] lb [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.ListBox = [COLOR=#0000ff]DirectCast[/COLOR](sender, ListBox)
    [COLOR=#0000ff]Dim[/COLOR] item [COLOR=#0000ff]As[/COLOR] MyError = [COLOR=#0000ff]DirectCast[/COLOR](lb.Items(e.Index), MyError)
    [COLOR=#0000ff]Dim[/COLOR] size [COLOR=#0000ff]As[/COLOR] [COLOR=#0000ff]New[/COLOR] Size(lb.ClientRectangle.Width, lb.ItemHeight)
    size = TextRenderer.MeasureText(item.Text, lb.Font, size)
    e.ItemHeight = size.Height
[COLOR=#0000ff]End[/COLOR] [COLOR=#0000ff]Sub[/COLOR]
 

Attachments

  • textrenderer.JPG
    textrenderer.JPG
    44.3 KB · Views: 442
Don, thanks for the feedback and example. What is the MyError object I don't see it defined in your code. Will this work in VS2003?

I'm still using VB2003 at work and VB2005 at home.

All your help is greatly appreciated!!!
 
The MyError class is just a placeholder class I created to test the multiple lines in a ListBox thingy.
This code won't work in .NET 1.1 because of the use of the System.Windows.Forms.TextRenderer class (new in .NET 2.0).
But don't panic: you can stil display mutiple lines in a ListBox.
You could add a Lines property to the class of the ListBox items (MyError in my example) that returns an array of string (or another container or collection like ArrayList or StringCollection, ...). And loop through the items of the returned container and draw the lines one by one:

In DrawItem event handler, instead of TextRenderer.DrawText:
VB.NET:
[COLOR=#0000ff]Dim[/COLOR] b [COLOR=#0000ff]As[/COLOR] [COLOR=#0000ff]New[/COLOR] SolidBrush(e.ForeColor)
[COLOR=#0000ff]For[/COLOR] index [COLOR=#0000ff]As[/COLOR] Int32 = 0 [COLOR=#0000ff]To[/COLOR] item.Lines.Count - 1
    e.Graphics.DrawString(item.Lines(index), lb.Font, b, e.Bounds.X, e.Bounds.Y + index * lb.ItemHeight)
[COLOR=#0000ff]Next[/COLOR]

[SIZE=2]b.Dispose()
[/SIZE]

And in MeasureItem eventHandler:
VB.NET:
[COLOR=#0000ff]Private[/COLOR] [COLOR=#0000ff]Sub[/COLOR] ListBoxErrorsMeasureItem([COLOR=#0000ff]ByVal[/COLOR] sender [COLOR=#0000ff]As[/COLOR] System.Object, [COLOR=#0000ff]_
ByVal[/COLOR] e [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.MeasureItemEventArgs) [COLOR=#0000ff]Handles[/COLOR] ListBoxErrors.MeasureItem
    [COLOR=#0000ff]Dim[/COLOR] lb [COLOR=#0000ff]As[/COLOR] System.Windows.Forms.ListBox = [COLOR=#0000ff]DirectCast[/COLOR](sender, ListBox)
    [COLOR=#0000ff]Dim[/COLOR] item [COLOR=#0000ff]As[/COLOR] MyError = [COLOR=#0000ff]DirectCast[/COLOR](lb.Items(e.Index), MyError)
    e.ItemHeight = item.Lines.Count * lb.ItemHeight
[COLOR=#0000ff]End[/COLOR] [COLOR=#0000ff]Sub[/COLOR]

This gives the same result.

If your own item class does not have a Lines property of some sort and you cannot add it (or you don't want to) you'll have to calculate the number of lines yourself and extract the lines from the text (with Split, ...).

And if you don't have linebreaks in the text you'll have even more work to do. But then I would suggest another approach altogether.
 
I'll play with these code samples! Thanks a bunch! I may have more questins for you later Don Delegate! :)
 
DrawItem & MeasureItem EventHandlers [Listbox]

Don, this is very helpful!!! :D

I was able to create my class called ErrClass with 5 strings and then add code to the DrawItem & MeasureItem event handlers as you stated and directed. It all works good. I even was able to draw lines at the top and bottom of each item in the listbox.

I have a few questions related to adding a textbox to the listbox. First is it possible to add a textbox to the listbox as an item? I figure I can use your same code to DirectCast() the textbox and Listbox like you showed. However, how do you draw an object like a textbox using owner drawn option? Is there a method on the textbox object to call?

Also, is there any way to recreate the DrawItem & MeasureItem code within my ErrClass object so that the ErrClass object is automatically drawn? Same question regarding the builtin textbox. [I know I can create a couple helper methods to my ErrClass and then just call them, but, I'm looking for a more inherent way to do this.]

I also am seeing the items once selected the forecolor font chances to white. Is there a way to make this Blue or some other color. Or, is there a way to repaint only the background? Seems like if you repaint the backcolor the way you did you over write your text object. I would not want to repaint all text items in my listbox when selecting each item. This text is for mainly display purposes anyway.

You have been extremely helpful!!! Thanks DonD. :)
 
Last edited:
Final Note:

Don Delegate/Everyone, I was able to create my own class with five string variables and inherited my class called ErrClass from "Object". I don't know if this inheritance from Object is necessary or not.

Anyway, I'm still trying to figure out if there is a way to .Add() a Textbox1 to a listbox control and redisplay it with text (multi-lines). I can add it and then using the DrawItem & MeasureItem event handlers use the Textbox1.Text property to display multiple lines in the listbox item. However, I have not figured out if it is possible to redisplay the whole Textbox1 it self. I'd be very interested if anyone can figure out how to do this.

Chow and Thanks!
 
Back
Top