Results 1 to 20 of 20

Thread: Flowlayoutpanel child controls?

  1. #1
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80

    Flowlayoutpanel child controls?

    I have a flowlayoutpanel, and i am dynamically adding empty pictureboxes to it. Then do a bunch of things. Then how do i add image to a certain pictureboxes in the panel? can i refer to the picturebox by name?

  2. #2
    JohnH's Avatar
    JohnH is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Dec 2005
    Location
    Norway
    Posts
    14,492
    Reputation
    2733
    can i refer to the picturebox by name?
    yes: flp.Controls("the name")

  3. #3
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    the name as in when you create the picturebox you put a name in picturebox.name ? hmm i thought i tried that. when i go flp.Controls("name").image , it always say image is not a member of control.

  4. #4
    IanRyder is offline VB.NET Forum All-Mighty
    .NET Framework
    .NET 4.0
    Join Date
    Sep 2012
    Location
    Healing, NE Lincs, UK
    Posts
    1,074
    Reputation
    710
    Hi,

    You need to cast the control to the correct type to access it's properties. i.e:-

    Code:
    Dim myImage As Image
    myImage = DirectCast(flp.Controls("Pic1"), PictureBox).Image
    Cheers,

    Ian.





  5. #5
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    Quote Originally Posted by Zexor View Post
    the name as in when you create the picturebox you put a name in picturebox.name ? hmm i thought i tried that. when i go flp.Controls("name").image , it always say image is not a member of control.
    The issue with that code is that Image is not a member of the Control class. Hopefully you have Option Strict On, in which case implicit conversions and late-binding are not permitted. All casts and conversions need to be explicit. The Controls collection of the form contains all the controls, including Buttons, TextBoxes and PictureBoxes. As such, the Item property, which you are using when you index the collection, returns everything as a Control reference. If you want to access members of a specific type of control then you must cast that reference as that type. Image is a member of PictureBox, not Control, so you must cast your Control reference as type PictureBox in order to access members of type PictureBox.

  6. #6
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    is it good practice to have Option Strict On? I seems to have a lot of implicit conversions and late binding.

  7. #7
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    It is very good practice to have Option Strict On. Most experienced developers lament the fact that Off is the default. That does make it easier for beginners to get simple things done but it also makes it much easier to break things as you get even a little bit more adventurous. I recommend turning it On for your current project and also in the IDE options so that it will be On by default for all future projects.

    It won't stop you writing any bad code though. In this case, in order to access a member of a PictureBox you must cast the Control reference as type PictureBox. If the control itself is not a PictureBox though, you'll still get an InvalidCastException. Your intent will be more obvious though and the location of the issue too.

  8. #8
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    i really don't understand how to fix late binding

    Code:
    Dim totalFiles As Integer = e.UserState(0)
    Code:
     sender.image =img

    all those give me late binding errors

    Code:
                bgwLoadImage.ReportProgress(i, {file.GetUpperBound(1), file(1, i), img, file(3, i), file(4, i), file(5, i)})
    and this say i cant infer an element type?

  9. #9
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    As I have said before, in order to access members of a certain type you have to have a reference of that type and if you don't have a reference of that type then you must cast. What is the type of 'e.UserState'? It's Object, right? Does Object have a default propery such that you can index it? No it doesn't. You have to cast 'e.UserState' as whatever type the object is that you assigned to it in the first place.

    The same goes for 'sender'. It is type Object and Object has no Image property. Presumably that's handling an event of a PictureBox so you need to cast 'sender' as type PictureBox.

    As for the last issue, if you want the compiler to infer the type of an array then all elements must have some common type other than Object, i.e. they must all be, inherit or implement some type other than Object. That is not the case for your code so you have to be explicit with the type of the array, i.e. you have to specify that it is type Object. That said, using an Object array like that is rather slack. You should either use a Tuple or else define your own type specifically for that purpose.

  10. #10
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    so first one is
    Code:
      Dim totalFiles As Integer = CInt(DirectCast(e.UserState, Object())(0))
    2nd one
    Code:
    DirectCast(sender, PictureBox).Image = img
    last one
    Code:
    bgwLoadImage.ReportProgress(i, New Object() {file(0, i), file(1, i), img, file(3, i), file(4, i), file(5, i), file.GetUpperBound(1)})
    i also have another one like this give error when run
    Code:
    tssl1.text = sender.tag(2).tostring
    tssl1.text = CStr(DirectCast(sender, PictureBox).Tag)(2)
    so much more complicated with all the casts, like this one is so much harder to read
    Code:
    Dim img As Image = e.UserState(2)
    Dim img As Image = DirectCast(DirectCast(e.UserState, Object())(2), Image)
    Last edited by Zexor; 10-23-2012 at 2:03 AM.

  11. #11
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    Firstly, noone said that you had to perform multiple casts on one line. You can break it up onto multiple lines if you want the code to be clearer. Secondly, if you had declared a typed specifically to pass the data rather than using an Object array then you would have much less casting to do. If you don't want all the casting then don't take the lazy option of using an Object array. That 2D array suggests more of the same. If you do it the proper way and declare types where it's appropriate then your code will be even more type-safe, more robust and easier to read.

  12. #12
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    i am saving some data in the tag of the picture box, so when i click it, i can just get it from the tag. how do you fix this late binding?
    Code:
    tssl1.Text = sender.Tag(2)
    like this??
    Code:
    tssl1.Text = DirectCast(sender, PictureBox).Tag(2).toString
    this still give last binding hmm

    Code:
    tssl1.Text = DirectCast(DirectCast(sender, PictureBox).Tag, Object())(2).ToString
    hehe 3 times longer
    Last edited by Zexor; 10-23-2012 at 2:30 AM.

  13. #13
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    Your point being? I reckon that it probably takes longer to build buildings to make them earthquake-proof. Maybe they shouldn't do that either. I mean, most of the time it won't matter so why bother?

    If it's such a drain on you to do the casting then, as I have said more than once, define your own types. You can inherit the PictureBox and add a property of the appropriate type and then use that property instead of the Tag. That's one less cast. You can also define a class to store the data with a property of the appropriate type for each value. That's another cast not required. I'm sure you're right though. They should just make everything an object. Why have I been wasting my time all these years?

  14. #14
    IanRyder is offline VB.NET Forum All-Mighty
    .NET Framework
    .NET 4.0
    Join Date
    Sep 2012
    Location
    Healing, NE Lincs, UK
    Posts
    1,074
    Reputation
    710
    Hi,

    Maybe I can try and put a fresh view on this for you and also give jmcilhinney a rest.

    To try and help you understand what jmcilhinney is trying to tell you please see the code below. Read through the comments carefully and hopefully you should be able to grasp what is being said to you.

    The first thing you have to realise is that you cannot treat the tag property as an array as it seems you are doing with .tag(2). What jmcilhinney is trying to tell you is that if you want to save multiple elements of data in the tag property then you have to do that by creating and using your own typed properties. This can be done by using Inheritance of the PictureBox class and expanding on it's existing properties or by creating a separate class to hold your data. In this example I will create a separate class to hold the additional data in the tag property.

    Create a new form, add a timer with enabled = true and interval = 2000. Also add a FlowLayoutPanel and name it flp. In the timer event change the image to an image on your own machine.

    Code:
    Public Class Form1
     
      Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        'I have used this timer to simulate the pictures being add to your own flow layout panel
        Static Counter As Integer
     
        'firstly create a SINGLE instance of the class that is going to hold all the details
        'that you want to save in the tag property of the picture box
        'See the class myTagDetails defined below to hold the information for the tag
        Dim myTagInfo As New myTagDetails
        With myTagInfo
          .PicName = "Sample Pic"
          .PicSize = 1000
          .TimeAdded = Now()
        End With
     
        'Now create the pciturebox for the new image and set whatever properties you need
        'finally add the myTagInfo variable to the tag property. Remember this is a single 
        'instance of the class but it has multiple properties
        Dim PicBox As New PictureBox
        With PicBox
          .Name = "PictureBox" & Counter
          .Image = My.Resources.BionatureLoginPic 'add your own picture here
          .Width = 50
          .Height = 50
          .Tag = myTagInfo
        End With
     
        'add the picturebox to the flowlayoutpanel and add an event handler for the click event
        flp.Controls.Add(PicBox)
        AddHandler PicBox.Click, AddressOf PictureBoxClicked
      End Sub
     
      Private Sub PictureBoxClicked(sender As System.Object, e As System.EventArgs)
        'so here is the event handler that is processed when each button is clicked
        'Firstly you will see that DirectCast is used to convert the sender object to type PictureBox
        Dim ClickedPicBox As PictureBox = DirectCast(sender, PictureBox)
        'Once we have got a Valid PictureBox type we can then convert the tag property which is now an object to its correct type
        'bring myTagDetails using the same principal as above
        Dim PicTagDetails As myTagDetails = DirectCast(ClickedPicBox.Tag, myTagDetails)
        'now that we have two correctly typed variables we can now do whatever we want with the selected picturebox.
        MsgBox(PicTagDetails.PicName)
        MsgBox(PicTagDetails.PicSize)
        MsgBox(PicTagDetails.TimeAdded)
      End Sub
     
      Private Class myTagDetails
        'Here we define a class that has multiple properties that be changed and modified as needed
        'Any variable type can be used here to do whatever you want
        Public Property PicName As String
        Public Property PicSize As Integer
        Public Property TimeAdded As DateTime
      End Class
    End Class
    Hope that helps.

    Cheers,

    Ian

  15. #15
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    Ok i am going to do that from now on. The code is much easier to read, thanks.
    But Why cant you treat .tag as an array? It's just an object? Can't you just put an object array in it?
    So i should make another class for e.UserState if i want to send an object array too?
    Last edited by Zexor; 10-23-2012 at 2:45 PM.

  16. #16
    JohnH's Avatar
    JohnH is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Dec 2005
    Location
    Norway
    Posts
    14,492
    Reputation
    2733
    Yes, Tag property type is Object, you can put anything in there. When getting it out again use CType/DirectCast to cast to the actual type it is.

  17. #17
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    I read that DirectCast is better than CType? But the compiler always do type convert with CType? Is DirectCast better?

  18. #18
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    12,834
    Reputation
    1621
    DirectCast will only work if the object is the specific type that you're casting as. CType will also perform conversions in cases where it's supported. For instance, this will work:
    Code:
    Dim o As Object = "100"
    Dim n As Integer = CType(o, Integer)
    while this will not:
    Code:
    Dim o As Object = "100"
    Dim n As Integer = DirectCast(o, Integer)
    If you're casting, use DirectCast.

  19. #19
    robben44 is offline VB.NET Forum Newbie
    .NET Framework
    .NET 1.1
    Join Date
    Oct 2012
    Posts
    3
    Reputation
    0
    For me DirectCast is better
    Last edited by robben44; 10-26-2012 at 5:00 AM.

  20. #20
    Zexor's Avatar
    Zexor is offline VB.NET Forum Miyagee
    .NET Framework
    .NET 4.5
    Join Date
    Nov 2008
    Posts
    409
    Reputation
    80
    I think DirectCast is twice as fast to convert value types.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Harvest time tracking