Filling a Listbox on a User Control

M

markr1000

I must have looked searched in 500+ places that showed up in Google
searchs, but not one has an example of what I want to do.

I have a Listbox on a User Control because I want to control the
visibility and/or presence of the Listbox and associated label, and I
want to encapsulate some of associated code.

I want to be able to pass the collection of strings that will fill the
Listbox to the User Control and have it pass on the collection to the
Listbox, preferably through Listbox.Items.AddRange.

Yet, I haven't been able to find *any* example of such a thing on the
Internet or in the C# books I have.

What is it that I'm missing?
 
P

Peter Duniho

[...]
I have a Listbox on a User Control because I want to control the
visibility and/or presence of the Listbox and associated label, and I
want to encapsulate some of associated code.

I want to be able to pass the collection of strings that will fill the
Listbox to the User Control and have it pass on the collection to the
Listbox, preferably through Listbox.Items.AddRange.

Well, the basic idea would be to retrieve the ListBox somehow and operate
on it directly from within code in your UserControl.

How you want to encapsulate that is up to you, and depends on who you want
to have direct access to the ListBox. But the ListBox itself is still
there an accessible by the usual means. You can reference it by name, or
you can enumerate the members of the UserControl's Controls collection,
looking for the ListBox (either by the Name property or by looking for
something that is a ListBox, for example).

What you want to do is not hard, and perhaps the simplicity of doing so is
why you are unable to find any examples. Perhaps you can be more specific
about what exactly you're having trouble with.

Pete
 
M

markr1000

[...]
I have a Listbox on a User Control because I want to control the
visibility and/or presence of the Listbox and associated label, and I
want to encapsulate some of associated code.
I want to be able to pass the collection of strings that will fill the
Listbox to the User Control and have it pass on the collection to the
Listbox, preferably through Listbox.Items.AddRange.

What you want to do is not hard, and perhaps the simplicity of doing so is
why you are unable to find any examples. Perhaps you can be more specific
about what exactly you're having trouble with.

The compiler objects to code like this added to the User Control
declaration

public void FillStockList(IEnumerable<String> StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList);
}

I get:

The best overloaded method match for
'System.Windows.Forms.ListBox.ObjectCollection.AddRange(System.Windows.Forms.ListBox.ObjectCollection)'
has some invalid arguments

and

Argument '1': cannot convert from
'System.Collections.Generic.IEnumerable<string>' to
'System.Windows.Forms.ListBox.ObjectCollection'

P.S. I'm new to C#, so I'm not only not sure what the syntax should
be, but also whether there isn't just a whole better way of passing
the data.
 
P

Peter Duniho

The compiler objects to code like this added to the User Control
declaration

public void FillStockList(IEnumerable<String> StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList);
}

I get:

The best overloaded method match for
'System.Windows.Forms.ListBox.ObjectCollection.AddRange(System.Windows..Forms.ListBox.ObjectCollection)'
has some invalid arguments

and

Argument '1': cannot convert from
'System.Collections.Generic.IEnumerable<string>' to
'System.Windows.Forms.ListBox.ObjectCollection'

Ah. Perhaps you can see how your intitial question was far too vague. :)

Anyway...

Take a look at the compiler error. It says that what you have is a
System.Collections.Generic.IEnumerable<string> and what you need is a
System.Windows.Forms.ListBox.ObjectCollection. If you look at the
documentation, you could also use an object[]. In fact, that's the
overload you really want...you get the other error, because that's the
first overload the compiler could find and couldn't find anything that
seemed like a better match to what you tried.

How do you get an object[]? Well, that's an array of objects. You need
to enumerate your StockList and build the array. If the original object
is actually something like List<String> which has a ToArray() method, then
you may find it more convenient to just pass the original object (it's not
clear from your code why you're using the IEnumerable<> interface, but if
it's not mandatory, it's not the most convenient data type to be using in
this situation).

In other words:

public void FillStockList(IEnumerable<String> StockList)
{
List<string> rgstrStock = new List<string>();

foreach (string strItem in StockList)
{
rgstrStock.Add(strItem);
}

lbxSubscribedStocks.Items.AddRange(rgstrStock.ToArray());
}

Or, if you can (List<> is just an example...you could use any type that
can convert to an array via something like the List<>.ToArray() method,
just use the appropriate conversion method):

public void FillStockList(List<string> StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList.ToArray());
}

Or, even better (if the data was in an array in the first place):

public void FillStockList(string[] StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList);
}

Pete
 
M

markr1000

Ah. Perhaps you can see how your intitial question was far too vague. :)

It was for trying to fix a specific problem, but I was trying to get
an answer for a general case. Still, I have noticed that people are
more willing to respond if code is included since it gives them
something concrete to look at.

How do you get an object[]? Well, that's an array of objects. You need
to enumerate your StockList and build the array. If the original object
is actually something like List<String> which has a ToArray() method, then
you may find it more convenient to just pass the original object (it's not
clear from your code why you're using the IEnumerable<> interface, but if
it's not mandatory, it's not the most convenient data type to be using in
this situation).

Only because I read Richter's suggestion in CLR via C# that you try to
be as generic in the parameters you pass as you can get away with.
Also, I wasn't interested in accessing any of the list items by index,
just pass them along. I hadn't found anything that identified ToArray
as something that AddRange would accept so I didn't realize that List
was needed.
Or, if you can (List<> is just an example...you could use any type that
can convert to an array via something like the List<>.ToArray() method,
just use the appropriate conversion method):

public void FillStockList(List<string> StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList.ToArray());
}

That's what I'm using. Thank you.
Or, even better (if the data was in an array in the first place):

public void FillStockList(string[] StockList)
{
lbxSubscribedStocks.Items.AddRange(StockList);
}

I've gotten into the habit of avoiding arrays unless the size is known
at compile time.
 
P

Peter Duniho

It was for trying to fix a specific problem, but I was trying to get
an answer for a general case. Still, I have noticed that people are
more willing to respond if code is included since it gives them
something concrete to look at.

Yes, that's true. I can't speak for anyone else, but to me when I see a
very vague, open-ended question, it's just too hard sometimes to try to
figure out what the person really wants to know. To answer the overly
vague question would require writing at least one chapter in a book, if
not the whole book.

It is always much better to be as specific as you can. If you want to
generalize based on responses you get from that sort of request, that is
always possible later.
Only because I read Richter's suggestion in CLR via C# that you try to
be as generic in the parameters you pass as you can get away with.

That advice is certainly not bad advice. It appears to me that in this
case, you went a little overboard, since the IEnumerable interface didn't
actually provide the functionality you needed. In other words, you
couldn't get away with using that as your parameter. :)
Also, I wasn't interested in accessing any of the list items by index,
just pass them along. I hadn't found anything that identified ToArray
as something that AddRange would accept so I didn't realize that List
was needed.

I agree that it is sometimes hard to make the connections implied in the
documentation. The AddRange() method clearly shows that you can pass an
object array ("object[]"). However, knowing where you might get one is
not always the easiest thing.

That said, of course the first place to start is to see where your data is
coming from and then seeing if it offers any direct way to get an array
from it. :)
[...]
I've gotten into the habit of avoiding arrays unless the size is known
at compile time.

I think that's overly conservative. IMHO, it's a good idea to not use
arrays if you don't know the size in advance of creating it, but this
information may be available at run-time. And the main reason to not use
arrays when you don't know the size in advance is that classes like List<>
offer convenient ways to resize a collection when necessary. I don't
think there's any performance advantage when using an array-based
collection versus an actual array (list-based collections, like
LinkedList<>, obviously do have a performance advantage since you can add
items without having to copy the whole data structure).

Anyway, sounds like you're back on track. Glad to hear it. :)

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top