Groups | Blog | Home
all groups > vb.net > february 2007 >

vb.net : Can I make a combobox that is stronly typed?


active
2/18/2007 5:02:20 PM
I'm using a ComboBox to display objects of a class I've defined, say CQQ.

Works great except somehow I occasionally set an Item to a String object
instead of an object of type CQQ.

It looks like Text replaces an item or something like that.

This results in a runtime error at which time I learn that the item that
should be CQQ is a String.

I can't find out where or how the setting happens.

It occurs to me that if the comboBox defined it's Items as objects of type
CQQ instead of Object it would the usage would be less error prone and more
likely to be bug free.

Is there some way I could generate a strongly typed combobox?

I know I could simply inherit a combobox and try to override anything the
changes an Item but that leaves the possibility that I'd miss some method
and not really have what I want. I'd like to just change the Items
collection once.

Is that possible?


Thanks


RobinS
2/18/2007 8:45:34 PM
Why not create a list of CQQ and then bind the combobox to it. Then to add
anything to the combobox, you'll have to add it to the list, which will
blow up if you try to add an object other than a CQQ to it. Off the top of
my head, something like this:

Dim myList As List(Of CQQ)

'add entries to the list
myList.Add(New CQQ("field1", "field2"))
myList.Add(New CQQ("field1", "field2"))
myList.Add(New CQQ("field1", "field2"))

myComboBox.DataSource = myList
myComboBox.DisplayMember = myList.field2
myComboBox.ValueMember = myList.field1

Robin S.
------------------------------------------
[quoted text, click to view]

active
2/19/2007 7:50:53 AM
Because I know nothing about using a datasource.

I'll look into what you've given below and see if I can learn enough to use
it.

There is also SetItemCore and SetItemsCore that I have to look into.


Thanks a lot

[quoted text, click to view]

active
2/19/2007 11:46:34 AM
I've used what you suggested almost with no changes.

Below is what I've tried and it appears to be storing data but not
displaying it.

I've tried everything I can think of for the DisplayMember!

StringWithInteger has two properties: Str and Value



Public myList As List(Of StringWithInteger) = New List(Of StringWithInteger)

and

myList.Add(itemValue) 'itemValue is type StringWithInteger

and

Public Sub New()

MyBase.New()

InitializeComponent()

Me.DataSource = myList

Me.DisplayMember = myList.field2

Me.ValueMember = myList.field1

End Sub







[quoted text, click to view]

RobinS
2/19/2007 1:20:06 PM
Can you show your class definition for StringWithInteger?

Robin S.
-------------------------------
[quoted text, click to view]

active
2/19/2007 1:22:47 PM
This is the attempt that seems like it should work but I get nothing in the
drop down box even though the debugger shows myList to have 187 items

[quoted text, click to view]
MyBase.DataSource = myList

MyBase.DisplayMember = "Str"

MyBase.ValueMember = "Value"


[quoted text, click to view]


Chris Dunaway
2/19/2007 2:12:56 PM
[quoted text, click to view]

Instead of using List(Of StringWithInteger), try using BindingList(Of
StringWithInteger)

Chris
active
2/19/2007 4:57:55 PM

[quoted text, click to view]

I did just that. In fact I gave the combobox properties so the form can
supply the List and set the DisplayMember and the ValueMember so the
combobox is somewhat general purpose.

However I don't know how to "unbind" the list and then rebind it.
I need to do that because changing the list after it is bound does not
change the boxes display.
That is, how do I undo .DataSource = myList

Thanks




thanks

[quoted text, click to view]

RobinS
2/19/2007 5:01:28 PM
I recommend you use a BindingSource component between the data source and
the combobox. You can drag one onto the form from the Toolbox, or create it
="on the fly".

Dim myBindingSource As BindingSource = New BindingSource()

myBindingSource.DataSource = myList

myComboBox.DataSource = myBindingSource
myComboBox.ValueMember = "whatever"
myComboBox.DisplayMember = "whatever"

Now when you change the list, the BindingSource will respond, and then
repaint the control. The BindingSource is sort of like lubrication between
the data source and the control. Putting it in the middle gives you a bunch
of methods and properties you can access, and better controls the bound
data and the display of it.

As Chris Dunaway recommended, you could define your list as a
BindingList(Of T), but you would still probably want to use a BindingSource
for the reason mentioned above.

Give this a try, and let me know how it works.

Robin S.
----------------------------
[quoted text, click to view]


active
2/19/2007 5:12:24 PM
I think I have a new problem now.
I don't know how to "unbind" the list and then rebind it.
I need to do that because changing the list after it is bound does not
change the box's display.
That is, how do I undo .DataSource = myList
so I can change myList and the rebind it?

Thanks


[quoted text, click to view]


I think I'm past the earlier problem now (see above) but since you asked
I've added the class below. I removed some to make it easier to read.

Public Class StringWithInteger
Private mInteger As Integer
Private mString As String

Public Sub New(ByVal str As String, ByVal value As Integer)
mString = str
mInteger = value
End Sub
Public Overrides Function ToString() As String
ToString = mString
End Function
Public Property Str() As String
Get
Str = mString
End Get
Set(ByVal text As String)
mString = text
End Set
End Property
Public Property Value() As Integer
Get
Value = mInteger
End Get
Set(ByVal numb As Integer)
mInteger = numb
End Set
End Property
End Class



active
2/19/2007 5:28:01 PM
Chris


[quoted text, click to view]
Chris, Does your reply relate to the above question or to the entire
requirement?
My next problem will relate to sorting the box's displayed list.
Does that impact the usage of either List or BindingList

Thanks
[quoted text, click to view]

RobinS
2/19/2007 7:40:45 PM

I figured the BindingSource would fix your problem.

For binding to a combobox, I think a BindingList is overkill. I use a
BindingList when binding a list of my business objects to a DataGridView so
I can access the methods and properties of the bindinglist and override
them as needed. There's no reason for you to not use a List() if it works
for you.

If you are loading the combobox from a datatable, sort it when you pull it
from the database. "Select LastName, FIrstName From MyCustomerTable ORDER
BY Lastname, FirstName".

If that's not viable, the BindingSource has sort capabilities. (See what I
mean about it having methods and properties you can use? Hubba hubba.)

For example, this will sort the data in my CustomersBindingSource by
ContactName in Ascending order.

CustomersBindingSource.Sort = "ContactName ASC"

There's probably also some kind of sort property on the combobox, but I'm
too tired to look it up. ;-)

[quoted text, click to view]

I think it's talking about when you want to change the data and save it
back to the data source, like when you are binding the data to a
DataGridView. You don't need to worry about that at this point.

I'm glad it's working. Good luck.
Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
-----------------------------------------------
[quoted text, click to view]

active
2/19/2007 9:36:10 PM
To update the display, what I previously had to do was rebind the list each
time I changed the list.
That seemed to work OK.
I inserted the BindingSource as you recommended and no longer need to rebind
after changes.
Chris Dunaway didn't really recommend. He suggested I try BindingList(Of T).
I did and didn't notice any difference.
I tried reading about all the stuff you and Chris suggested - but my
background is lacking and it is pretty slow going.
So I really want to thanks you for all the help. Now at least I know what I
need to read until I understand it.
Strange to have it working and not understand what is going on.

The List class seems a little simpler so I'd prefer to stay with that unless
there is a strong reason to use BindingList - is there such a reason?

I've been looking at internet sites trying to find out how to sort the
ComboBox display. Can you easily point me to something that would help?

Thanks again for all the help!

PS
I still make changes by changing the list.
The BindingSource doc seemed to say that changes in the data can be made
through it. Should I be looking at doing that?



[quoted text, click to view]

Cor Ligthert [MVP]
2/19/2007 10:18:46 PM
Active,

If you know nothing from a datasource, why do you than try to use it direct
on your own usercontrol.

Can you not first try it as Robin show you on a normal combobox and then
start to implement that on your own usercombobox?

Just my thought,

Cor

" active" <activeNOSPAM@a-znet.com> schreef in bericht
news:%23pXZ5LFVHHA.3592@TK2MSFTNGP03.phx.gbl...
[quoted text, click to view]

active
2/20/2007 8:30:56 AM
I have a feeling I'm taking advantage of you good nature, but I can't stop!

After I wrote last night, I found the SortedList generic class

Which works OK and produces a sorted display.

However, there is something I can't figure out:

I need to get the integer part of StringWithInteger (Value) of the selected
item

I got this far
= DirectCast(StringWithIntegerComboBox1.SelectedItem, SortedList(Of String,
StringWithInteger))

StringWithInteger has two properties Str and Value

I don't think I want to cast to SortedList but something like
SortedList.Item

That's my present problem.

Thanks again

I'll also try List with the sort method you pointed out but I would like to
know how to do the above.



a smaller problem is in understanding. I continue to use

StringWithIntegerComboBox1.ItemDisplayMember = "Str"

StringWithIntegerComboBox1.ItemValueMember = "Value"

With List there was only one object so I could see how that might work.

With SortedList there are two objects and I wonder how it finds the property

It appears to find it because I tried

StringWithIntegerComboBox1.ItemDisplayMember = "qqStr"

StringWithIntegerComboBox1.ItemValueMember = "qqValue"

and this produced an exception which makes me think that it was using the
original one - not ignoring them

Suppose both objects had a property "Value", then what?









[quoted text, click to view]

RobinS
2/20/2007 2:56:48 PM

You're on the right path with the DirectCast, but you need to cast it to
the object that is in the sortedlist, not to a SortedList itself.

In your sorted list, I'm assuming StringWithInteger is still a class with
both fields in it. Did you try this:

myItem = _
DirectCast(StringWIthIntegerComboBox1.SelectedItem, _
StringWithInteger)

Debug.Print(myItem.str)
Debug.Print(myItem.Value.ToString)

As for the data binding, my guess would be it sorts by the first value, but
it retains the list of objects (second value). So it data binds to the
objects in the list, and only uses the key to sort them.

Robin S.
------------------------------------------

[quoted text, click to view]

active
2/21/2007 10:08:58 AM
I came up with the following for SortedList(Of String, StringWithInteger)

'ControlGenericComboBox1.SelectedItem is of type:
System.Collections.Generic.KeyValuePair(Of String, .StringWithInteger)

'And has properties Key and Value

and

DirectCast(ControlGenericComboBox1.SelectedItem,
System.Collections.Generic.KeyValuePair(Of String,
StringWithInteger)).Value.Numb

where Numb is a property of my class



Also, ComboBox disallows sort if a datasource is used.



Also, with

List(Of StringWithInteger)

I couldn't get the following to work.

The doc's seem to say it should.

BindingSource1.Sort = "Str ASC"

Just occurred to me: I wonder if

System.Collections.Generic.KeyValuePair

applies here.



Thanks for all the help





[quoted text, click to view]
RobinS
2/21/2007 9:51:03 PM
Now I don't know what the heck you're doing. Please post your class
definition for StringWithInteger, what you're using to create a list of
them, and the code you are using to bind the combobox.

Robin S.
---------------------------------------------
[quoted text, click to view]
active
2/22/2007 8:29:44 AM
I've been trying both List and SortedList
The below DirectCast is for SortedList and it works well so I thought I
include it in case someone else needed it.

I've posted the code for StringWithInteger and your prior help related
correctly to that and List.
I should have mentioned in the last post that the DirectCast pertained to
SortedList, not List.
It would have been nice to find out why my Sort does not work with List but
I leave that for another time.
I'm ready to move on, thanks to your help.



[quoted text, click to view]

RobinS
2/22/2007 4:28:27 PM
You're welcome. I'm glad you got it to work for you.
Robin S.
------------------------------
[quoted text, click to view]

AddThis Social Bookmark Button