0

I am trying to display a line of pictures in my program. But I am having a problem, where it is only showing the first image in the imagelist and only showing one image-box.

Private Cards As New List(Of PictureBox)
  Private Sub SetupCards()

    For i As Integer = 0 To imglist1.Images.Count - 1
        Dim PicCard As PictureBox = New PictureBox()
        PicCard.Width = 100
        PicCard.Height = 200
        PicCard.Top = 50
        PicCard.Left = 50
        Me.Controls.Add(PicCard)
        PicCard.Image = imglist1.Images(i)
        Cards.Add(PicCard)
    Next i
  End Sub
Robert Caden
  • 19
  • 11
  • maybe it would be better if you work with arrays in this case. already tried it? – Marco Sadowski Feb 08 '18 at 09:20
  • No, could you show me what that might look like? –  Feb 08 '18 at 09:21
  • Why are there two separate "Add" calls? – George Birbilis Feb 08 '18 at 09:22
  • 1
    It looks like your PicturesBoxes are stacking up on top of each other. Each one is starting at the same point. – Mary Feb 08 '18 at 09:23
  • Btw, List is a data structure class, not some ListBox-style control. – George Birbilis Feb 08 '18 at 09:24
  • @MarcoSadowski : Why would arrays be a better choice? A `List(Of T)` is essentially an array with add/remove capabilities. – Visual Vincent Feb 08 '18 at 09:27
  • @GeorgeBirbilis : There are two `Add` calls because one adds the picture boxes to the form, and the other adds it to his list of cards. – Visual Vincent Feb 08 '18 at 09:29
  • Okay, so I am displaying a set of "cards" that need to show randomised images, loaded in from a image list. I need to be able to click the card and check what image is in it. Would a List be suitable for this or an array? –  Feb 08 '18 at 09:32
  • Oh sorry for my mistake @Visual Vincent - I'm more familiar with arrays then with List. – Marco Sadowski Feb 08 '18 at 09:32
  • See my answer, just need a container control. That will act as a list and control the lifetime of those added controls. No need for extra complexity of syncing two separate lists – George Birbilis Feb 08 '18 at 09:32
  • @GeorgeBirbilis : Okay, so if I don't use a List(Of T), wouldn't it not be possible to check for what image I am clicking on in a different subroutine? –  Feb 08 '18 at 09:37
  • @MarcoSadowski : That's okay, though calling it a mistake seems rather harsh :). -- A `List(Of T)` works the same way as an array apart from some added capabilities (like adding or removing items). It uses an array internally that it modifies every time you add/remove items. – Visual Vincent Feb 08 '18 at 09:41
  • @David : It is possible to check which one you are clicking regardless if you use a separate list or not, _however_ as I said in my comment on George's answer there's no reason _**not**_ to use your own list. Infact, having a separate list makes modifying and keeping track of your cards a lot easier. – Visual Vincent Feb 08 '18 at 09:43
  • Since PictureBox is a control (descendent type), if the container maintains a list of controls/children, you can cast those to PictureBoxes again. – George Birbilis Feb 08 '18 at 12:15
  • Also, probably recent versions of .net languages may allow you to cast a List of say Control to a List of some descendent of control. Alternative (if the vb/c# compilers still aren't clever enough to do it) is to make a wrapper class and wrap a control list to appear as a PictureBox list by delegating all calls to it with appropriate typecasts – George Birbilis Feb 08 '18 at 12:19
  • @GeorgeBirbilis : `if the container maintains a list of controls/children, you can cast those to PictureBoxes again` - While that may be, the original order of the controls are not guaranteed when you iterate the `Control.Controls` collection, in which case he'd have to implement additional `If`-statements to ensure he's accessing the correct picture box. He'd also have to ensure that what he's iterating is infact a `PictureBox`, as there can be other controls in the container as well (which, if they exist, cause unnecessary iteration). – Visual Vincent Feb 08 '18 at 14:51
  • I'd expect only containers with overlapping (Z-ordering) allowed to change the order of their items in the controls list, others should just keep them in the order they were added (addition should occur to end or to start of list depending on how the container is implemented). Indeed though it's a point to keep in mind. – George Birbilis Feb 11 '18 at 09:15
  • btw, if they control what is added to the container programmatically there's no chance something else exists in it. Esp. if you don't pass its reference to external code - if you do pass such have to check they don't add null anyway if the lists don't do it themselves - of course for casted lists you'd also have to check if somebody added an ancestor object instead of the specific one by casting the list you passed to them. Anyway, wouldn't expect an API to pass lists of controls to outside world, just lists of data (aka list of some Picture, not PictureBox) – George Birbilis Feb 11 '18 at 09:23

2 Answers2

1

You're placing the picture boxes on top of each other, which is why you only see the last card. You've got to set a different Left property for every picture box you add.

The solution is rather simple. Just add the picture box's width to Left, multiplied by the current index i.

PicCard.Left = 50 + PicCard.Width * i
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
-2

Don't need to keep the imaging controls in your own list if you add them to a parent container control.

Use ListView or third-party controls, or use custom drawing code if you need to use ListBox (which wraps respective Windows control). See C# Can I display images in a list box?

George Birbilis
  • 2,782
  • 2
  • 33
  • 35
  • 1
    Hey, this isnt c#. This is vb.net –  Feb 08 '18 at 09:33
  • The reason for the separate list is so that he can keep track of the cards and modify them. The container control (the form) might have more controls added to it, which makes iterating the cards much harder (and annoying) without the separate list. There's no reason for him _not_ to use it. – Visual Vincent Feb 08 '18 at 09:35
  • The container should be a ListView, not the form, and obviously will keep just the image controls in that. Then they may use an indexed property or a list property to mask the list view container's controls collection if they need to expose a list of images to the outside world. No need for two data containers. Syncing them is needless complexity – George Birbilis Feb 08 '18 at 09:41
  • He doesn't need to sync them if he's only modifying the list once (that is, when adding them the first time). Besides, seeing as this is for a card game it's harder to make a `ListView` look good on your play area rather than just having picture boxes. There's nothing wrong with keeping a separate list. A lot of people do for various reasons (both newcomers and professionals). It's quite common when it comes to making a game like this. – Visual Vincent Feb 08 '18 at 09:49
  • 1
    Also, regarding syncing the lists: Keep in mind that a `PictureBox` is a reference type, which means that an item in his list points to the **exact** same picture box as the respective one on the form. Thus if he modifies the picture box in the list it the one on the form will update as well (as long as he doesn't replace the item itself). -- The only thing he would actually need to sync is when he adds or removes a picture box (which isn't a hard thing to sync at all). Though if he codes this right, he might not have to do that either as he can just hide the already existing picture boxes. – Visual Vincent Feb 08 '18 at 09:57
  • Syncing means that he needs to track those references (addition/removal) in both lists. Also sample referenced is C#, but the same thing is in VB.net, WinForms library is language agnostic in that matter – George Birbilis Feb 08 '18 at 12:22