Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
849 views
in Technique[技术] by (71.8m points)

.net - Change the image from multiple dynamic picturebox

I'm making a contactlist with VB.NET with status images. I'm loading this list from MSSQL but when i reload the list it flickers.

This list is a TableLayoutPanel with dynamic created pictureboxes and labels.

My question is:

How can i change my image inside a dynamic picturebox when u reload my contacts instead of reloading the entire list.

My code to create the table:

While UserData.Read

    If UserData("Status").ToString = "Online" Then

        If UserData("NieuwBericht").ToString = "Ja" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.greenchat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greenbubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        ElseIf UserData("NieuwBericht").ToString = "Nee" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.greenchat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greybubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        End If

    ElseIf UserData("Status").ToString = "Afwezig" Then

        If UserData("NieuwBericht").ToString = "Ja" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.orangechat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greenbubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        ElseIf UserData("NieuwBericht").ToString = "Nee" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.orangechat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greybubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        End If

    ElseIf UserData("Status").ToString = "Offline" Then

        If UserData("NieuwBericht").ToString = "Ja" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.redchat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greenbubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        ElseIf UserData("NieuwBericht").ToString = "Nee" Then

            Dim newPictureBox As New PictureBox
            newPictureBox.Image = My.Resources.redchat
            newPictureBox.Visible = True
            newPictureBox.Width = 30
            newPictureBox.Height = 30
            newPictureBox.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox)

            Dim newPictureBox2 As New PictureBox
            newPictureBox2.Image = My.Resources.greybubblechat
            newPictureBox2.Visible = True
            newPictureBox2.Width = 30
            newPictureBox2.Height = 30
            newPictureBox2.SizeMode = PictureBoxSizeMode.Zoom
            newPictureBox2.Name = UserData("Username").ToString
            ChatContactList.Controls.Add(newPictureBox2)

            Dim newLabel As New Label
            AddHandler newLabel.Click, AddressOf Chatbox
            newLabel.Text = UserData("Voornaam").ToString & " " & UserData("Achternaam").ToString
            newLabel.Name = UserData("Username").ToString
            newLabel.Font = New Font("Microsoft sans serif", 12)
            newLabel.Dock = DockStyle.Fill
            newLabel.TextAlign = ContentAlignment.MiddleLeft
            newLabel.Visible = True
            ChatContactList.Controls.Add(newLabel)

        End If

    End If

End While

Image of my contactlist

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A UserControl is a bit like a subform. It is a container for an assortment of controls which act together or represent some logical unit. In this case, it would be the visual representation of some user states (properties). Rather than creating and managing individual controls, you can put them on one UC and encapsulate much of the code to manage them.

In the Solution Explorer window, right click, select Add, then pick UserControl. I added a TableLayoutPanel, 2 PictureBoxes and a Label (all with proper names of course). There is also an ImageList with a quick grab of your images:

enter image description here

This alone replaces many many lines of code you have to create new controls and then setting the same properties over and over again. To make them act as a logical object, you can add properties which abstracts the minutiae of selecting images etc:

Public Class Chatter

    Public Enum ChatStatus
        Unknown
        Online
        Away
        Offline
    End Enum

    Public Enum ChatMsgStatus
        Undefined      ' kludge to force the initial state
        Unknown
        [New]
        Read
    End Enum

    ' one set of images for all chatter instances
    Private Shared Imgs As Image()

    Public Property ChatId As Int32         ' or guid?

    Private chName As String = ""
    Public ReadOnly Property ChatName As String
        Get
            Return chName
        End Get
    End Property

    Private mStatus As ChatMsgStatus = ChatMsgStatus.Undefined
    Public Property MsgStatus As ChatMsgStatus
        Get
            Return mStatus
        End Get
        Set(value As ChatMsgStatus)
            If (value <> mStatus) Then
                Select Case value
                    Case ChatMsgStatus.New
                        pbMStatus.Image = Imgs(3) 
                    Case ChatMsgStatus.Read
                        pbMStatus.Image = Imgs(4)
                    Case Else
                        pbMStatus.Image = Imgs(4)
                End Select
            End If
            mStatus = value
        End Set
    End Property

    Private chStatus As ChatStatus = ChatStatus.Unknown
    Public Property Status As ChatStatus
        Get
            Return chStatus
        End Get
        Set(value As ChatStatus)
            If value <> chStatus Then
                Select Case value
                    Case ChatStatus.Online
                        pbUStatus.Image = Imgs(0)
                    Case ChatStatus.Away
                        pbUStatus.Image = Imgs(1)
                    Case ChatStatus.Offline
                        pbUStatus.Image = Imgs(2)
                    Case Else
                End Select
            End If
            chStatus = value
        End Set
    End Property

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        If Imgs Is Nothing Then
            Imgs = New Image() {My.Resources.ChatUserGrn, My.Resources.ChatUserYlw, 
               My.Resources.ChatUserRed, My.Resources.ChatBalloonGrn,
               My.Resources.ChatBalloonGry}

               ' see note
        End If
    End If
        ' Add any initialization after the InitializeComponent() call.
    End Sub
    ' no need to create one without Identifiers
    Public Sub New(n As Int32, cname As String)
        MyClass.New()
        ' default intitial values:
        chName = cname
        ChatId = n

        lblChName.Text = cname
        Me.Status = ChatStatus.Online
        Me.MsgStatus = ChatMsgStatus.Unknown
    End Sub
End Class

(Edit) I didn't like the result using an ImageList. This version, loads an array of images from resources. Aside from only loading one copy of GreenUser for use by all users, it allows you to tailor it as needed. For instance change the backcolor to SystemColors.Window to match the user's theme. If you also use a label instead of a picturebox, you can use the Text property for "?" or even indicate the number of new messages.

I am sure there is more to it and I can think of several things I would want it to know (for instance overlay the green balloon with the number of unread messages). But the point here are the concepts of encapsulation, DRY and reusable code.

When you compile it, there will be a new Chatter control in the toolbox. Add some at runtime using the properties exposed:

Dim c As New Chatter(42, "Ziggy von Hausen")
flpChat.Controls.Add(c)

c = New Chatter(14, "ThDutoit")
c.MsgStatus = Chatter.ChatMsgStatus.New
flpChat.Controls.Add(c)

c = New Chatter(78, "Plutonix")
c.Status = Chatter.ChatStatus.Offline
flpChat.Controls.Add(c)

c = New Chatter(4, "Codexer")
c.MsgStatus = Chatter.ChatMsgStatus.New
c.Status = Chatter.ChatStatus.Away
flpChat.Controls.Add(c)

The Id would be something to uniquely identify each chat participant. The name is not usually enough (SO has over 50 pages of people named "Steve") and you will want a way to identify to link a control to a user. (An alternative, would be a ChatterBox reference in the user list which is a reference to the related UserControl:

Dim user = "Codexer"

Dim chatter = flpChat.Controls.
            OfType(Of Chatter).
            FirstOrDefault(Function(c) c.ChatName.StartsWith(user))
If chatter IsNot Nothing Then
    chatter.Status = chatter.ChatStatus.Online
End If

It is sub optimal to search each time and an Id would be better than a mere name. The ideal would be for a ChatUser class with all the other stuff the app has to store by user. The class should include a reference to the control so that when the status changes or whatever, the class could simply:

myChatterBox.Status = myStatus

Result:

enter image description hereenter image description here

Certainly they can be created with considerably less code. In the course of things, you can change the status of either image by just setting the related property.

As an added benefit, because you are no longer creating individual controls, and because UserControl inherits from Component you dont have to worry about leaks if/when these are removed.

A Must Read:
Creating a Windows Form User Control


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...