How does one (if at all possible) display a unique bitmap or icon beside the text for each item in a combobox?
The VB .Net combobox supports the BackgroundImage and Image properties.
Many thanks in advance
Printable View
How does one (if at all possible) display a unique bitmap or icon beside the text for each item in a combobox?
The VB .Net combobox supports the BackgroundImage and Image properties.
Many thanks in advance
Thanks, I'll check them out
Here is a VB.NET translation of the C# class. It works pretty good. Its easiest if you just draw a normal combo on the form and then change in auto generated code from the ComboBox to ComboBoxEx.
VB Code:
Public Class ComboBoxEx Inherits ComboBox Private _imageList As ImageList Public Property ImageList() As imageList Get Return _imageList End Get Set(ByVal value As imageList) _imageList = value End Set End Property Public Sub New() DrawMode = DrawMode.OwnerDrawFixed End Sub Protected Overrides Sub OnDrawItem(ByVal ea As DrawItemEventArgs) ea.DrawBackground() ea.DrawFocusRectangle() Dim item As ComboBoxExItem Dim imageSize As Size = ImageList.ImageSize Dim bounds As Rectangle = ea.Bounds Try item = CType(Items(ea.Index), ComboBoxExItem) If item.ImageIndex <> -1 Then ImageList.Draw(ea.Graphics, bounds.Left, bounds.Top, item.ImageIndex) ea.Graphics.DrawString(item.Text, ea.Font, New SolidBrush(ea.ForeColor), bounds.Left + imageSize.Width, bounds.Top) Else ea.Graphics.DrawString(item.Text, ea.Font, New SolidBrush(ea.ForeColor), bounds.Left, bounds.Top) End If Catch e As Exception If ea.Index <> -1 Then ea.Graphics.DrawString(Items(ea.Index).ToString(), ea.Font, New SolidBrush(ea.ForeColor), bounds.Left, bounds.Top) Else ea.Graphics.DrawString(Text, ea.Font, New SolidBrush(ea.ForeColor), bounds.Left, bounds.Top) End If finally MyBase.OnDrawItem(ea) End Try End Sub Public Class ComboBoxExItem Private _text As String Private _imageIndex As Integer = -1 Public Property Text() As String Get Return _text End Get Set(ByVal Value As String) _text = Value End Set End Property Public Property ImageIndex() As Integer Get Return _imageIndex End Get Set(ByVal Value As Integer) _imageIndex = Value End Set End Property Public Sub New() MyBase.new() End Sub Public Sub New(ByVal text As String) MyBase.new() Me.Text = text End Sub Public Sub New(ByVal text As String, ByVal imageIndex As Integer) _text = text _imageIndex = imageIndex End Sub Public Overrides Function ToString() As String Return _text End Function End Class End Class
Being the absolute moron I am, I can't figure out how to properly implement the example. I changed all of the control references in code and the error when I try to compile is:
"Reference to a non-shared member requires an object reference"
Here is the code I'm using:
Dim MyList As New ArrayList()
MyList.Add(New GenericList("Jack Hammer", 1))
MyList.Add(New GenericList("Sledge Hammer", 2))
MyList.Add(New GenericList("Screwdriver", 3))
MyList.Add(New GenericList("Wrench", 4))
'bind list
ComboBoxEx.DataSource = MyList
ComboBoxEx.DisplayMember = "Display"
ComboBoxEx.ValueMember = "ID"
As you can see, I'm trying to combine both examples you posted.
Thanks again for your expert advice on this, have a great weekend
Well unforunately that ComboBox Extender class isn't made to take other items with images except the ComboBoxExItem class. You can still use binding but you couln'd have the Items be of the type GenericList. Although You could have another class either implement a common interface or inherit from the ComboBoxExItem class and do it that way. But when the ComboBoxEx overrides the OnPaint event of the normal ComboBox it uses the ImageIndex and Text properties to display the item with a picture. Or you could go through and devise some type of ImageIndexMember type property for it.
If you want to use the ComboBoxExItems then you can do this:
VB Code:
Dim al As New ArrayList() al.Add(New ComboBoxEx.ComboBoxExItem("Test1", 1)) al.Add(New ComboBoxEx.ComboBoxExItem("Test2", 0)) al.Add(New ComboBoxEx.ComboBoxExItem("Test3", 1)) al.Add(New ComboBoxEx.ComboBoxExItem("Test4", 0)) al.Add(New ComboBoxEx.ComboBoxExItem("Test5", 1)) ComboBox1.ImageList = ImageList1 ComboBox1.DataSource = al ComboBox1.DisplayMember = "Text" ComboBox1.ValueMember = "ImageIndex"
Here is a version that can display an image for anything that implements ImageComboBox.IImageComboItem and a sample of the genericlist class extended to implement the interface.
Although I think it'd be better to Just workin a ImageMember proeprty so I'm going to try that next.
Actually this one is much better because you don't need to implement anything just set the imageindexmemeber property of the ImageComboBox and you are good to go.
That is a perfect example :) Can't believe it's actually that simple!
Once again, thanks a million for your help, I wish Microsoft provided example code like that.
Best regards,
George
When I add your classes into my project everything is fine except for one small problem:
Me.ComboBox1 = New ImageComboBinding.ImageComboBox()
it underlines the above line, and I can't find any other reference for "ImageComboBinding" anywhere in the project. Help!!
Figured it out, ImageComboBinding is the name of the "solution". Hehehe, sorry about that.
Once again, thanks for your help
ImageComboBinding was the namespace of the example project, so if you moved the classes over then there is no more ImageComboBinding namespace. Also I added a constructor that takes a standard combo and converts it to the ImageCombo but I'm not sure if it was in that version. That way you don't have to mess with any autogenerated code (which sometimes gets rewritten) you just add a normal code to the form set it up and then change it in the form load event. So if this doesn't work:
Then let me know and I'll load the newer version.VB Code:
Dim icbo As ImageComboBox Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'ini the imagecombo icbo = New ImageComboBox(ComboBox1, Me)
Sorry I was typing while you were posting.
icbo = New ImageComboBox(ComboBox1, Me)
Please do post the latest, it generates a compiler error of:
"too many arguments to public sub New()
Thanks in advance,
George
Here you go.
Works like a charm! Thanks again. I hope others are tuning into this thread.
Best regards,
George
p.s. I havn't cursed at Microsoft for a few days now :)
I have run into the problem that if the ComboBox is on a tabpage instead of on the main form, then it won't populate with any items unless I put the combobox on the main form. Should I create a combobox class for the tabsheet itself? Any suggestions or help you can give me on this would be greatly appreciated.
Thanks in advance
First try changing the Auto Generated text instead of using Passing in a normal combo to the constructor to create it. The code in there doesn't grab all the properties from the normal combo and that may be it. I tried to get it to loop through the properties but that had a few bugs so try that first.
That solved the problem. I just scares me to change the auto-generated stuff because at one point all of the controls vanished from the form I was working on (although it didn't do that this time). Thanks again Edneeis!
Have a great weekend
If you figure out what properties can and can't be set then we can fix the constructor way. Its just when I tried to set them all the list wouldn't appear then. So I just tried to manually set all the properties I thought would be needed. Hmmm, actually I just realized something that may fix it....
I'll catch up with you on Monday, have a good one, and thanks again for the help on this
Sorry fixed it and forgot to post it.
Replace this constructor:
Public Sub New(ByRef cbo As ComboBox, frm as Form)
With this instead:
VB Code:
Public Sub New(ByRef cbo As ComboBox) 'assign all properties from cbo to me 'Dim pi As Reflection.PropertyInfo 'For Each pi In cbo.GetType.GetProperties ' Dim s As String = pi.Attributes.ToString ' If pi.CanWrite Then ' 'On Error Resume Next 'just in case ' Me.GetType.GetProperty(pi.Name).SetValue(Me, pi.GetValue(cbo, Nothing), Nothing) ' End If 'Next 'TODO: have it consume ALL properties of original combo Me.Anchor = cbo.Anchor Me.BackColor = cbo.BackColor Me.BackgroundImage = cbo.BackgroundImage Me.CausesValidation = cbo.CausesValidation Me.ContextMenu = cbo.ContextMenu Me.DataSource = cbo.DataSource Me.DisplayMember = cbo.DisplayMember Me.Dock = cbo.Dock Me.DropDownStyle = cbo.DropDownStyle Me.DropDownWidth = cbo.DropDownWidth Me.Enabled = cbo.Enabled Me.Font = cbo.Font Me.ForeColor = cbo.ForeColor Me.IntegralHeight = cbo.IntegralHeight If cbo.Items.Count > 0 Then Dim tmp(cbo.Items.Count) As Object cbo.Items.CopyTo(tmp, 0) Me.Items.AddRange(tmp) End If Me.MaxDropDownItems = cbo.MaxDropDownItems Me.MaxLength = cbo.MaxLength Me.Sorted = cbo.Sorted Me.Text = cbo.Text Me.TabStop = cbo.TabStop Me.ValueMember = cbo.ValueMember Me.Visible = cbo.Visible Me.Location = cbo.Location Me.Size = cbo.Size Me.TabIndex = cbo.TabIndex 'set to ownerdraw Me.DrawMode = DrawMode.OwnerDrawFixed 'switch combos Dim parent As Object = cbo.Parent parent.Controls.Remove(cbo) parent.Controls.Add(Me) End Sub
Then just pass in the combo it is replacing instead of the combo and form.
icbo = New ImageComboBox(ComboBox1)