ListBox with custom items (colors, images, text alignment)
Hey,
Here is a very simple owner-drawn ListBox control that allows you to specify a Color and Image for each item. It uses a very simple method to only allow items of a specific type (and not all Objects as usual) which is easily extended.
I know you could just use a ListView for this, but I came across this method when creating a different control (a 'large item' listbox that looks like the Downloads window in FireFox) and decided to share it, because it is conceptually easy and allows you to extend the items much more. For example, there's nothing stopping you to give each item it's own Font or something.
As a 'bonus' there is also a TextAlign property which allows you to align the text of all items to whichever side you want (MiddleLeft in the image).
How it works:
The ColorListBox class inherits ListBox, and overloads the Items property. Instead of returning MyBase.Items, it returns its own ColorListBoxItemCollection.
The original base items are then returned by a (private) property baseItems.
Public Overloads ReadOnly Property Items() As ColorListBoxItemCollection
Get
Return _Items
End Get
End Property
'The original items that the user will never see.
Private ReadOnly Property baseItems() As ObjectCollection
Get
Return MyBase.Items
End Get
End Property
The ColorListBoxItemCollection inherits System.Collections.ObjectModel.Collection(Of ColorListBoxItem) and overrides the Set/Remove/InsertItem and ClearItems methods. In those methods, it adds the item to it's collection but also adds the item to the baseItems property of the owner ColorListBox. This is necessary because the ColorListBox won't draw any items in your own custom collection; only those in the MyBase.Items collection.
vb.net Code:
Protected Overrides Sub ClearItems()
MyBase.ClearItems()
_listBox.baseItems.Clear()
End Sub
Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As ColorListBoxItem)
MyBase.InsertItem(index, item)
_listBox.baseItems.Insert(index, item)
End Sub
Protected Overrides Sub RemoveItem(ByVal index As Integer)
MyBase.RemoveItem(index)
_listBox.baseItems.RemoveAt(index)
End Sub
Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As ColorListBoxItem)
MyBase.SetItem(index, item)
_listBox.baseItems(index) = item
End Sub
Finally, the ColorListBox is owner drawn, so it overrides the OnDrawItem method. The listbox actually wants to draw the original items, but I simply force it to use the items from my own collection (by using their index), and draw them with the correct color and possibly with an image.
As I said, this is the 'base' for a different ListBox control which I'll hopefully also complete shortly.
I am not 100% sure whether this method will always work (I am afraid the baseItems and Items might become 'de-synchronised' for some reason for example), but I hope it will work fine.
Re: ListBox with custom items (colors, images, text alignment)
You don't need to add any code, the code is all in the vb file. If you added the control without problems then all you need to do is build the project and it will be in your toolbox like any other control.
Re: ListBox with custom items (colors, images, text alignment)
I'd like to detect clicked regions in each and every item from the ColorListBox, but i dunno what has to be done in this class of yours to accomplish that. Wouldn't you have any idea would you?
Maybe creating an other method "ItemClickedSpot"? But then, how?
Private Sub ColorListBox1_ClickedHotSpot(ByVal Index As Integer, ByVal Spot As ColorListBox.HotSpots, ByVal Tag As String) Handles ColorListBox1.ClickedHotSpot
Re: ListBox with custom items (colors, images, text alignment)
Ok, a couple of suggestions:
1. Instead of handling the MouseDown event of your own class, you should generally override the OnMouseDown method instead. It has the same end effect, but there are a few reasons why that approach is better (I can't remember any though...)
2. You seem to be hardcoding the 'hotspots' by their X and Y values. What if you decide to shift an icon 2 pixels? Then you'd need to change your code... Not very desirable I think!
What you can do instead is make use of the fact that my ListBox is using custom items; the ColorListBoxItem class. As of now, it has only three properties (Text, Color and Image), but you can add to that of course.
Why not add a few Rectangle properties that represent your hotspots. You would have a property for every hotspot (Icon1, Icon2, Icon3, ItemImage, etc), representing the bounds of that hotspot.
Then, in your MouseDown event (or OnMouseDown override, see point 1), you can retrieve the item that the mouse is clicked on, and then check if the click location is inside any of the hotspots:
vb.net Code:
For i As Integer = 0 To Me.Items.Count - 1
If Me.GetItemRectangle(i).Contains(e.Location) Then
' This is your item
Dim item As ColorListBoxItem = Me.Items(i)
If item.Icon1.Contains(e.Location) Then
RaiseEvent ClickedHotSpot(... Icon1)
ElseIf item.Icon2.Contains(e.Location) Then
RaiseEvent ClickedHotSpot(... Icon2)
'etc
End If
' We've already found our item so stop looking
Exit For
End If
Next
Now, if you want to shift/enlarge/whatever Icon2 (for example), you just change the Icon2 Rectangle property of the item, and your code still works.
You can do the same in the OnMouseMove method and OnMouseUp method to simulate a button; change the border of the icon when the mouse is moving over the item, change it another way when the mouse is down, and change it back when the mouse is up.
How you're going to implement that depends on how you're drawing the icons. I suppose you have edited the OnDrawItem method so that it draws the icons too? By the way, if you have, you can make use of the Icon1, Icon2, etc properties too. Just draw the icon using those Rectangles.
Last edited by NickThissen; May 23rd, 2010 at 05:24 PM.
Re: ListBox with custom items (colors, images, text alignment)
Good point...the square around the icons!
Thanks
(important, ItemHeight must be 70)
Here's how your class looks like in my implementation...i'm still twicking it so it's supposed to have a few bugs..
Here's how it's looking at the moment
Last edited by TDQWERTY; May 24th, 2010 at 05:22 AM.
Re: ListBox with custom items (colors, images, text alignment)
You have the source code, so why not take a look? If you have a specific question I'd be happy to answer it, but try to see it in the source code first, it's not very hard at all.
Re: ListBox with custom items (colors, images, text alignment)
i get error when i try to buld my solution with the control added
Error 1 'down' is not a member of 'Resources'. ColorListBox2.vb 128 34
Error 2 'up' is not a member of 'Resources'. ColorListBox2.vb 134 34
Error 3 Type 'OwnerDrawnListBox' is not defined. ColorListBox2.vb 446 14
Error 4 'CreateGraphics' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 456 29
Error 5 'ItemHeight' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 457 9
Error 6 'Font' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 457 50
Error 7 'Items' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 464 25
Error 8 'SelectedIndex' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 464 34
Error 9 sub 'OnPaint' cannot be declared 'Overrides' because it does not override a sub in a base class. ColorListBox2.vb 484 29
Error 10 'OffScreen' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 491 57
Error 11 'BackColor' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 492 49
Error 12 'ClientRectangle' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 492 64
Error 13 'VScrollBar' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 498 17
Error 14 'VScrollBar' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 498 41
Error 15 Name 'DrawCount' is not declared. ColorListBox2.vb 498 63
Error 16 'Items' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 501 21
Error 17 'Font' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 502 33
Error 18 'Items' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 504 38
Error 19 'SelectedIndex' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 507 20
Error 20 'ClientSize' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 508 98
Error 21 'VScrollBar' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 508 124
Error 22 'VScrollBar' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 508 147
Error 23 'ItemHeight' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 508 172
Error 24 'ForeColor' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 513 29
Error 25 'Items' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 516 40
Error 26 'ItemHeight' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 517 line 24
Error 27 'OffScreen' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 521 line 30
Error 28 sub 'OnPaintBackground' cannot be declared 'Overrides' because it does not override a sub in a base class. ColorListBox2.vb 528 line 29
Error 29 'ClientSize' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 529 line 62
Error 30 'ClientSize' is not a member of 'color_listbox.FontListBox'. ColorListBox2.vb 529 line 87
Programming is all about good logic. Spend more time here
Re: ListBox with custom items (colors, images, text alignment)
i have no idea how to use this
walkthrough please :
1 how to add the control ?
2 how to customize the control ?
3 where do i put the code of post 1, is it neccesary ?
Re: ListBox with custom items (colors, images, text alignment)
Just add the file to your project and build the solution, then it should come up in the toolbox as usual. Drag it to your form and add items via the Items property.
You don't need the code of post 1, that is already in the control, I just posted it to clarify how it works in case anyone was interested.
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by NickThissen
Just add the file to your project and build the solution, then it should come up in the toolbox as usual. Drag it to your form and add items via the Items property.
You don't need the code of post 1, that is already in the control, I just posted it to clarify how it works in case anyone was interested.
i downloaded : colorlistbox.vb
how do i add it from vb.net ?
you also said "then build the solution" what is that supposed to mean ? how ?
project (on the menu) then what ?
walkthrough please
Re: ListBox with custom items (colors, images, text alignment)
See your Solution Explorer toolwindow. Rightclick the project you want it to be used in and select "Add - Add Existing File". Choose the .vb file and add it. Then go to the Build menu and select Build solution (or rightclick the project and select Build from there). If the build succeeds (you can see this in the output window) when there are no errors then the control should appear at the top of the toolbox.
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by TDQWERTY
Good point...the square around the icons!
Thanks
(important, ItemHeight must be 70)
Here's how your class looks like in my implementation...i'm still twicking it so it's supposed to have a few bugs..
Here's how it's looking at the moment
hello, there is a bug in your control. when you click and item then click another, the previous doesn't return to the normal state.
have you corrected this, can you tell me how?
Programming is all about good logic. Spend more time here
Re: ListBox with custom items (colors, images, text alignment)
how do you check for duplicate items, I'm adding folder path, i want to check for duplicate, I'm using this code, but there is a problem, Its say "Value of type 'String' cannot be converted to 'ColorListBoxItem'.", it usually work on the normal listbox but this one is not working
If fFolder.ShowDialog = DialogResult.OK Then
If Not lstFolder.Items.Contains(fFolder.SelectedPath) Then
lstFolder.Items.Add(fFolder.SelectedPath, Color.Black, My.Resources.FolderHorizontal)
End If
End If
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by rojaldearintok
how do you check for duplicate items, I'm adding folder path, i want to check for duplicate, I'm using this code, but there is a problem, Its say "Value of type 'String' cannot be converted to 'ColorListBoxItem'.", it usually work on the normal listbox but this one is not working
If fFolder.ShowDialog = DialogResult.OK Then
If Not lstFolder.Items.Contains(fFolder.SelectedPath) Then
lstFolder.Items.Add(fFolder.SelectedPath, Color.Black, My.Resources.FolderHorizontal)
End If
End If
If you look at the ColorListBoxItem class, you will see there is a Text property that you can use.
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by yvne
Not sure why it's erroring like that in the ToolBox, when I have this control in my project's it shows at the very top (once I've compiled the project) and it has a purple gear icon. Maybe you could try removing it from your toolbox, recompile your project and see if it shows up at the very top.
Regardless of the toolbox issue, when you manually add it to a form does it still function normally?
Currently using VS 2015 Enterprise on Win10 Enterprise x64.
Re: ListBox with custom items (colors, images, text alignment)
Hi there.
Sorry for necroing this thread, but I have a question about this awesome custom control.
I'm using this custom control to list visited websites that were bookmarked by the user. I've coded a procedure, which allows the user to see the URL corresponding to the bookmark, which is being hovered by the mouse.
Everything works perfectly, but the control flickers like there's no tomorrow ...
Is there a way to remove or at least considerably reduce the flickering? I've tried the doublebuffered property on the form itself, but that doesn't work.
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by Simbiose
Everything works perfectly, but the control flickers like there's no tomorrow ...
Is there a way to remove or at least considerably reduce the flickering? I've tried the doublebuffered property on the form itself, but that doesn't work.
Instead of setting DoubleBuffered on the Form try setting DoubleBuffered in the control(s) that flicker, like in the constructor of the ColorListBox class...
Code:
Public Class ColorListBox
Inherits ListBox
#Region " Constructor "
Public Sub New()
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
Me.DoubleBuffered = True
' .....
Re: ListBox with custom items (colors, images, text alignment)
Originally Posted by Edgemeal
Instead of setting DoubleBuffered on the Form try setting DoubleBuffered in the control(s) that flicker, like in the constructor of the ColorListBox class...
Code:
Public Class ColorListBox
Inherits ListBox
#Region " Constructor "
Public Sub New()
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
Me.DoubleBuffered = True
' .....
Lol! Major D'OH. Why is my brain thinking this way?
Well, the double buffer works, but only if the listbox items don't have a really long bookmark and/or really long URL, which rarely happens lol...
I probably need to do a bit more of tweaking of the drawing event I guess.
Re: ListBox with custom items (colors, images, text alignment)
FML! You can't set the listbox item image on run-time? You can only do it be using the Properties Window of the listbox?
The data is loaded into the listbox from a fed datatable, so I can only define the images for each item on run-time ............
Any work around for this?
Edit* *Hard facekeyboard* You CAN set the listbox item image on run-time... what was happening to me, was that I have a textbox that has a textchanged event that handles the way that the adapter feeds the datatable and consequently the datatable would be in charge of adding items to the listbox.
So whenever I loaded the form, the textbox would add items to the listbox, instead of the load event of the form (which was where I was handling the item image adding).
All I had to do was add the images on the textbox event
Last edited by Simbiose; Dec 26th, 2014 at 07:37 AM.
Re: ListBox with custom items (colors, images, text alignment)
I removed the link to your email address. Posting that in a forum post is not a good idea, as it will be sucked up by a bot and you'll end up with lots of spam.
I'm not clear whether your question is regarding the custom listbox in this thread or in some other design. If it isn't based on the techniques discussed in this thread, then you should create your own thread over in the .NET forum for the question.