0

I'm trying to add pictureboxes dynamically in vb.net.

If i play with the vars, changing the "i" value i can add the images and the event to the last picturebox created (i can only click the last images).

But when i use the code below, it says the there's something out of boundaries ( Index outside the bounds of the matrix ).

What am i doing wrong? Tks

Imports System.IO

Public Class FormMain
Dim Path1 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\1.png"
Dim Path2 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\2.png" 

Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    CreateImages()
End Sub

Dim i As Integer
Dim Logo(i) As PictureBox

Sub CreateImages()
    Dim i As Integer = TextBoxNumberImages.Text

    For i = 0 To i - 1
        Logo(i) = New PictureBox
        Logo(i).Name = "Image" + Str(i)
        Panel1.Controls.Add(Logo(i))
        Logo(i).Image = Image.FromFile(Path1)
        Logo(i).SizeMode = PictureBoxSizeMode.StretchImage

        AddHandler Logo(i).Click, AddressOf _Click

    Next
End Sub

'------ADD EVENT----

Dim IsImageSelected(i) As Boolean 

Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)

    If IsImageSelected(i) = False Then
        Logo(i).Image = Image.FromFile(Path2)
        IsImageSelected(i) = True
    Else
        Logo(i).Image = Image.FromFile(Path1)
        IsImageSelected(i) = False
    End If
End Sub

----EDIT----

I just changed the var declaration to inside of the function:

Sub CreateImages()
    Dim i As Integer = TextBoxNumberImages.Text
    Dim Logo(i) As PictureBox

    For i = 0 To i - 1
        Logo(i) = New PictureBox
        Logo(i).Name = "Image" + Str(i)
        Panel1.Controls.Add(Logo(i))
        Logo(i).Image = Image.FromFile(Path1)
        Logo(i).SizeMode = PictureBoxSizeMode.StretchImage

        AddHandler Logo(i).Click, AddressOf _Click

    Next
End Sub

Now it creates the images the way i want, but i can't access the pictureboxes in the event. Help?

i.Dio
  • 177
  • 1
  • 2
  • 16
  • First turn on Option Strict. then read up on [Scope in VB](http://stackoverflow.com/a/33249045/1070452). DIM is creating a new, different Logo array each time so you really have 2-3 of them. Since you wont know how many there are until runtime, use a list rather than an array – Ňɏssa Pøngjǣrdenlarp Dec 30 '16 at 16:33
  • @Plutonix yes i realized that now. Thank you, the answer above is perfect. Ty – i.Dio Dec 30 '16 at 16:44
  • 1
    No. 'Perfect' would implement Option Strict – Ňɏssa Pøngjǣrdenlarp Dec 30 '16 at 16:45
  • @Plutonix In my project i have both On now and it's still ok. Am i suppose to look at something in the code below? i.e., any other idea? – i.Dio Dec 30 '16 at 16:49
  • `Dim i As Integer = TextBoxNumberImages.Text` wont compile under Option Strict because a textbox contains only text not integer. I am not sure why the project setting doesnt do it (maybe you really looked at the settings default for VS?), but `Option Strict On` at the top of the code file will do it. – Ňɏssa Pøngjǣrdenlarp Dec 30 '16 at 16:52
  • 1
    It would be better to use `Integer.TryParse` so if they enter `I like Pie` you can catch it – Ňɏssa Pøngjǣrdenlarp Dec 30 '16 at 17:01
  • @Plutonix `Dim i As Integer = CInt(TextBoxNumberImages.Text)` instead ? edit: Oh okay. I get it now ! – i.Dio Dec 30 '16 at 17:02

1 Answers1

0

Don't use an array, use a List(Of PictureBox) instead. You could also store the selected state in the Tag() of the PictureBox. To get a reference to the PictureBox that was clicked, cast the Sender parameter. All together it would look something like this:

Private Logo As New List(Of PictureBox)

Sub CreateImages()
    Dim i As Integer = TextBoxNumberImages.Text

    For i = 0 To i - 1
        Dim pb As New PictureBox
        pb = New PictureBox
        pb.Tag = False ' <-- initial not selected state
        pb.Name = "Image" + Str(i)
        Panel1.Controls.Add(pb)
        pb.Image = Image.FromFile(Path1)
        pb.SizeMode = PictureBoxSizeMode.StretchImage
        AddHandler pb.Click, AddressOf _Click
        Logo.Add(pb)
    Next
End Sub

Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim pb As PictureBox = DirectCast(sender, PictureBox)
    Dim selected As Boolean = DirectCast(pb.Tag, Boolean)
    If selected = False Then
        pb.Image = Image.FromFile(Path2)
    Else
        pb.Image = Image.FromFile(Path1)
    End If
    pb.Tag = Not selected ' toggle selected state
End Sub
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Thank you! And i really apreciate the idea of using the `tag` – i.Dio Dec 30 '16 at 16:45
  • On a side note, if you need to access the PBs in the List, you can still access them "by index" similar to an array: `Logo(i).xxx = yyy` – Idle_Mind Dec 30 '16 at 16:54