Access added (sub) control in VB .NET - vb.net

With this code I dynamicly add a panel with two panels inside (a header and a data panel). Within the Data panel there is also a label that I like to access.
Now I like to access the label inside the data panel but can't reach it with:
test_label.text = "this a second test"
Here the dynamicaly added panels
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim newPanelMain As Panel = New Panel With {
.Location = New Point(200, 500),
.Name = "test",
.Size = New Size(500, 500)
}
Dim newPanelHeader As Panel = New Panel With {
.Name = newPanelMain.Name & "_header",
.BackColor = Color.Orange,
.Dock = DockStyle.Top,
.Height = 50
}
newPanelMain.Controls.Add(newPanelHeader)
Dim newPanelData As Panel = New Panel With {
.Name = newPanelMain.Name & "_data",
.Dock = DockStyle.Fill,
.BorderStyle = BorderStyle.FixedSingle
}
newPanelMain.Controls.Add(newPanelData)
Dim newPanelSize As Panel = New Panel With {
.Name = newPanelMain.Name & (("_size")),
.BackColor = Color.Red,
.Height = 20,
.Width = 20,
.Location = New Point(newPanelData.Width - 20, newPanelData.Height - 20)
}
newPanelData.Controls.Add(newPanelSize)
Dim newLabel As Label = New Label With {
.Text = "This is a test",
.Name = newPanelMain.Name & (("_label")),
.Location = New Point(0, 0),
.AutoSize = True
}
newPanelData.Controls.Add(newLabel)
Me.Controls.Add(newPanelMain)
End Sub

Declare newLabel as a member variable:
Private newLabel As Label
So you can use this code:
Me.newLabel = New Label With {
.Text = "This is a test",
.Name = newPanelMain.Name & (("_label")),
.Location = New Point(0, newPanelHeader.Height + 10),
.AutoSize = True
}
newPanelData.Controls.Add(Me.newLabel)
And then change its .Text property using:
Me.newLabel.Text = "this a second test"
In a different situation (e.g. if you have multiple Labels created at runtime) remember that you can use Control.ControlCollection class:
CType(CType(Me.Controls("test"), Panel).Controls("test_data"), Panel).Controls("test_label").Text = "this is a third test"

Related

Getting the famous "NullReferenceException" error while building form with dynamic groupboxes in VB.NET

Of course I've searched through all types of forums relating to the "NullReferenceException" error and they all say that my objects = nothing and that I need to use the "new' operand to make it work.
I'm building my Form dynamically using groupboxes and then inserting labels and textboxes in each groupbox. Some textboxes will need to be regularly updated but I don't want to update the whole form unnecessarily since it makes the Form flicker when updating(I've tried).
I've was able to build my form normally using the "new groupbox" function but was unable to access objects in each of the groupboxes once it was built. Maybe it has something to do with the fact that I didn't make an indexed array out of the groupboxes. Rebuilding the whole Form was my only way to refresh he displayed values, but like I stated, it makes the the Form flicker.
So I tried to make an indexed array out of the Groupboxes, this is where I get the "NullRefereceException" error. I've already declare my Groupbox array.
Public Shared GrpBox as GroupBox()
Here is my code at this point:
For j As Integer = 0 To Thermostats.Count - 1
Dim ThermostatName As String
Dim Model As String
Dim IPAddress As String
With Thermostats(j)
ThermostatName = .ThermostatName
Model = .Model
IPAddress = .IPAddress
End With
GrpBox(j) = New GroupBox() With {
.Location = New Point(265, 27),
.Size = New Size(253, 176),
.Text = ThermostatName,
.BackColor = Color.White,
.FlatStyle = BorderStyle.Fixed3D,
.BackgroundImage = Imagelist1.Images(0),
.Margin = New Padding(20, 30, 0, -10)
}
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(146, 65),
.AutoSize = True,
.Text = "Heat To",
.Font = New Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(210, 80),
.AutoSize = True,
.Text = TempUnit,
.Font = New Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(146, 110),
.AutoSize = True,
.Text = "Cool To",
.Font = New Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(210, 125),
.AutoSize = True,
.Text = TempUnit,
.Font = New Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(15, 66),
.Size = New Size(125, 15),
.Text = "Current Temperature",
.Font = New Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(90, 80),
.AutoSize = True,
.Text = TempUnit,
.Font = New Font(FontFamily.GenericSansSerif, 24, FontStyle.Bold),
.Visible = True
})
GrpBox(j).Controls.Add(New Label() With {
.Location = New Point(20, 20),
.AutoSize = True,
.Text = Model,
.Font = New Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
.Visible = True
})
Dim TxtCool As New TextBox() With {
.Location = New Point(150, 125),
.Size = New Drawing.Size(60, 25),
.Visible = True,
.Enabled = False,
.BackColor = Color.White,
.ForeColor = Color.Black,
.BorderStyle = BorderStyle.FixedSingle,
.Font = New Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold),
.Text = 23.0 '
}
GrpBox(j).Controls.Add(TxtCool)
Dim TxtHeat As New TextBox() With {
.Location = New Point(150, 80),
.Size = New Size(60, 25),
.Visible = True,
.Enabled = False,
.BackColor = Color.White,
.ForeColor = Color.Black,
.BorderStyle = BorderStyle.FixedSingle,
.Font = New Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold),
.Text = 20.5
}
GrpBox(j).Controls.Add(TxtHeat)
Dim TxtActualTemp As New TextBox With {
.Location = New Point(19, 82),
.Size = New Drawing.Size(75, 45),
.Visible = True,
.Enabled = False,
.BackColor = Color.White,
.ForeColor = Color.Black,
.BorderStyle = BorderStyle.FixedSingle,
.Font = New Font(FontFamily.GenericSansSerif, 24, FontStyle.Bold),
.Text = (6 * Rnd() + 19)
}
GrpBox(j).Controls.Add(TxtActualTemp)
Me.TblLytPnl.Controls.Add(GrpBox(j))
Next

Swap positions between three Panels

I have three panel type objects (A, B, and C), which have been dynamically generated within another panel type control.
My question is, how can I exchange panel B to the position of panel A and panel A to the position of panel B? This will be triggered by a click on a ToolStripMenuItem.
What I had thought, was to go through the arrangement of panels to know who exists and from there to work them, is that correct?
For Each obj As Control In Panel1.Controls
MsgBox(obj.Name)
Next
This is the code that I use to move to right:
Private Sub ToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem1.Click
Dim clickedPanel = DirectCast(DirectCast(DirectCast(sender, ToolStripMenuItem).Owner, ContextMenuStrip).SourceControl, Panel)
clickedPanel.Location = New Point((clickedPanel.Location.X + 120), clickedPanel.Location.Y)
End Sub
This is the code I use to generate objects dynamically:
Private Sub TileNavItem5_ElementClick(sender As Object, e As NavElementEventArgs) Handles TileNavItem5.ElementClick
Dim pos As Int32 = cInt(TextBox38.Text)
Dim poslabel As Int16 = cInt(TextBox42.Text)
Dim posY As Int16 = 330
Dim posX As Int16 = 3
Panel1.AutoScrollPosition = New Point(0, 0)
Dim pb As New Panel With
{
.Width = 120,
.Height = 460,
.Top = 10,
.Left = 10,
.BorderStyle = BorderStyle.FixedSingle,
.BackgroundImage = Image.FromFile("C:\example.bmp"),
.BackgroundImageLayout = ImageLayout.Stretch,
.ContextMenuStrip = CntxtMnuStrpSection,
.Name = "Panel" & Val(TextBox37.Text)
}
AddHandler pb.Click, AddressOf myClickHandler_b
Dim labela As New Label With {
.AutoSize = True,
.Location = New Point((poslabel), 12),
.Text = "Section " & CInt(TextBox37.Text),
.ForeColor = Color.White,
.BackColor = Color.Transparent,
.Font = New Font(Me.Font, FontStyle.Bold),
.Name = "Label" & CInt(TextBox37.Text)
}
pb.Location = New Point(0, 0)
pb.Location = New Point(pos, 20)
Panel1.Controls.Add(pb)
pb.Controls.Add(labela)
For j = 1 To 4
Dim pbdoors As New Panel With
{
.Width = 114,
.Height = 98,
.Top = 10,
.Left = 10,
.BorderStyle = BorderStyle.FixedSingle,
.BackgroundImageLayout = ImageLayout.Stretch,
.ContextMenuStrip = CntxtMnuStrpUnit,
.Name = "Unit" & Val(TextBox37.Text) & j
}
AddHandler pbdoors.Click, AddressOf myClickHandler_doors
pbdoors.Location = New Point(posX, posY)
pb.Controls.Add(pbdoors)
posY = (posY - 100)
Next
Panel1.AutoScrollPosition = New Point(Panel1.HorizontalScroll.Maximum, Panel1.VerticalScroll.Maximum)
TextBox37.Text = CInt(TextBox37.Text) + 1
TextBox38.Text = Val(TextBox38.Text) + 120
End Sub
You just need to find the controls. Swapping is the easy part.
Finding controls is also easy if you use Control.Controls.Find(String, Boolean). But you must at least know the control's name.
The difficulty comes in here
' TextBox37.Text = CInt(TextBox37.Text) + 1 ' implicit conversion from int to string
TextBox37.Text = (CInt(TextBox37.Text) + 1).ToString()
where you must find the control by name and you have built some integer into the name. Can you keep track of how many times 1 is added to TextBox37.Text?
If you can, you can pass it into this function, and the swapping will be performed
Private Sub swap(index1 As Integer, index2 As Integer)
' build the panel names
Dim p1Name = $"Panel{index1}"
Dim p2Name = $"Panel{index2}"
' find the panels
Dim p1 = DirectCast(Panel1.Controls.Find(p1Name, True).FirstOrDefault(), Panel)
If p1 Is Nothing Then Throw New ArgumentException("index1")
Dim p2 = DirectCast(Panel1.Controls.Find(p2Name, True).FirstOrDefault(), Panel)
If p2 Is Nothing Then Throw New ArgumentException("index2")
' swap the panels
Dim temp = p2.Location
p2.Location = p1.Location
p1.Location = temp
End Sub
swap(1, 2) will swap panel 1 with 2. swap(4, 6) will swap the panel 4 with 6. This logic is not included in your question (i.e. how many times is TileNavItem5_ElementClick called?), so you know better how to incorporate it. I hope it works for you.

Add an extra control to a button in VB.Net

I have a code that creates 30 buttons at run time on a form which works excellently
For i = 0 To 30
btn = New Button
Dim old As Padding = btn.Margin
Dim old2 As Padding = btn.Padding
btn.Tag = "X1"
btn.Name = "Drane"
btn.Text = "The power of trying"
btn.Width = 95
btn.Height = 120
btn.Margin = New Padding(10, 10, 10, 10)
btn.Padding = New Padding(0, 4, 0, 2)
btn.TextAlign = ContentAlignment.BottomCenter
btn.ImageAlign = ContentAlignment.TopCenter
btn.Font = New Font("Lucida Sans Unicode", 11)
btn.ForeColor = Color.Black
btn.BackColor = Color.White
Next i
Now I'm trying to add an extra control to hold the ids for buttons that I created at run time
btn.id = i
which would hold the ids of each particular button so I can get the value in other functions in my application. I know I have to add this somehow as a control but I just don't know how.
Please any help will be greatly appreciated in resolving this
This will extend the Button class and add an ID property.
Public Class ButtonMod
Inherits Button
Public Property ID As Integer
End Class
Then you just create them in a loop as you were doing already:
For i As Integer = 1 To 30
Dim btn As New ButtonMod
Dim old As Padding = btn.Margin
Dim old2 As Padding = btn.Padding
btn.Tag = "X1"
btn.Name = "Drane"
btn.Text = "The power of trying"
btn.Width = 95
btn.Height = 120
btn.Margin = New Padding(10, 10, 10, 10)
btn.Padding = New Padding(0, 4, 0, 2)
btn.TextAlign = ContentAlignment.BottomCenter
btn.ImageAlign = ContentAlignment.TopCenter
btn.Font = New Font("Lucida Sans Unicode", 11)
btn.ForeColor = Color.Black
btn.BackColor = Color.White
btn.ID = i
Next

How do I put something in front of an image?

Using VB.net VS2010 and Winforms, I am simply trying to add both a picturebox and a label to a panel, but the label will not go in front of the picture box. How can I set the label as the foremost object? Using the code below, the label always ends up behind the picturebox.
Public Class MyTab
Inherits System.Windows.Forms.Panel
Public myText As New Label
Public tab_top_left as New Picturebox
Public Sub New(ByVal tab_object As tab_properties_object)
With tab_top_left
.BackgroundImage = My.Resources.tab_top_left
.Parent = Me
.Location = New Point(0, 0)
.SendToBack()
.Width = 20
.Height = 19
.Name = "tab_top_left"
End With
Dim TextString As String = tab_object.top_tab_text
myText.Font = CustomFont.GetInstance(Main.main_font_size_up3, FontStyle.Regular)
myText.ForeColor = Color.FromArgb(255, 0, 0, 0)
myText.BackColor = Color.FromArgb(255, 204, 204, 204)
myText.Text = TextString
myText.Location = New Point(0, 0)
myText.Width = 200
myText.Height = 40
myText.UseCompatibleTextRendering = True
myText.BorderStyle = BorderStyle.None
myText.Name = "tab_" & myText.Text
myText.Parent = Me
myText.BringToFront()
Me.Width = myText.Left + textSize.Width + 15
Me.Height = 40
Me.Name = "_" & TextString
Me.Location = New Point(0, 0)
End Sub
End Class

Programming dynamic panels in VB.NET

My programming experience is short and I have written several applications but am very much still a novice in VB.NET.
I am writing an application which requires information to be displayed in panels. These panels need to be created at runtime based upon the information from a database. The database contains the information and I will create the panels and put the data into it. The data will be dynamic labels which will update with information to the user.
My problem is that I've never really created dynamic controls before and I seem to be having problems. If I select one item in the database to be created then it works fine. More than one is where I'm having the issue. It goes through the code and adds the controls to the form but only actually displays the last panel it created. The space on the form where the other panels should be is blank.
Also, I want to refer to the dynamically created panels after they are created. I am giving them each a unique name as they are created. Obviously I can't refer to their name directly in the IDE, Is there another way of referencing the name I am giving them?
My code is below, if anyone can point me in the right direction as to what I'm missing and doing wrong it would be much appreciated.
Dim cmd03 As OleDb.OleDbCommand = New OleDb.OleDbCommand(Nothing, strConnection)
Dim strMachineID As String = String.Empty
Dim strMachineIP As String = String.Empty
Dim strMTB As String = String.Empty
Dim MachinePanel As New Panel
Dim MachineName As New Label
Dim MachineStatus As New Label
Dim RunningProg As New Label
Dim RunningPart As New Label
Dim PartsComplete As New Label
Dim startpointX As Integer = 12
Dim startpointY As Integer = 82
Try
cmd03.CommandText = "Select * FROM tblMachines WHERE tblMachines.Monitor = TRUE"
strConnection.Open()
Dim myreader02 As OleDb.OleDbDataReader = cmd03.ExecuteReader(CommandBehavior.CloseConnection)
While myreader02.Read
strMachineID = myreader02.GetValue(0)
strMachineIP = myreader02.GetValue(10)
strMTB = myreader02.GetValue(1)
MachinePanel.Name = "pnl" & strMTB & strMachineID
MachinePanel.Size = New Point(918, 120)
MachinePanel.Location = New Point(startpointX, startpointY)
MachinePanel.BackColor = Color.White
'MachinePanel.Visible = True
'MachinePanel.Enabled = True
MachineName.Name = "lbl" & strMTB & strMachineID
MachineName.Text = strMTB & Chr(32) & strMachineID
MachineName.Font = New Font("Bookman Old Style", 26, FontStyle.Bold)
MachineName.Location = New Point(4, 34)
MachineName.AutoSize = True
MachineStatus.Name = "lbl" & strMTB & strMachineID & "status"
MachineStatus.Text = "?Unknown?"
MachineStatus.Font = New Font("Bookman Old Style", 22.2, FontStyle.Bold)
MachineStatus.Location = New Point(380, 34)
MachineStatus.AutoSize = True
MachineStatus.Enabled = True
MachineStatus.Visible = True
RunningProg.Name = "lbl" & strMTB & strMachineID & "prog"
RunningProg.Text = "prog????"
RunningProg.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
RunningProg.Location = New Point(760, 9)
RunningProg.AutoSize = True
RunningPart.Name = "lbl" & strMTB & strMachineID & "part"
RunningPart.Text = "part????"
RunningPart.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
RunningPart.Location = New Point(760, 44)
RunningPart.AutoSize = True
PartsComplete.Name = "lbl" & strMTB & strMachineID & "complete"
PartsComplete.Text = "complete????"
PartsComplete.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
PartsComplete.Parent = MachinePanel
PartsComplete.Location = New Point(760, 78)
PartsComplete.AutoSize = True
' PartsComplete.Enabled = True
'PartsComplete.Visible = True
Me.Controls.Add(MachinePanel)
MachinePanel.Controls.Add(MachineName)
MachinePanel.Controls.Add(MachineStatus)
MachinePanel.Controls.Add(RunningProg)
MachinePanel.Controls.Add(RunningPart)
MachinePanel.Controls.Add(PartsComplete)
MachinePanel.Visible = True
MachinePanel.Enabled = True
MachinePanel.Show()
startpointY = startpointY + 140
End While
Catch ex As Exception
Finally
strConnection.Close()
End Try
End Sub
First, turn option strict on as MachinePanel.Size = New Point(918, 120) accepts a Size structure and not a Point structure. Secondly you'll need to create a new instance of each object in each cycle.
While myreader02.Read
MachinePanel = New Panel() '
MachineName = New Label()
MachineStatus = New Label()
RunningProg = New Label()
RunningPart = New Label()
PartsComplete = New Label()
With MachinePanel
.Name = "pnl" & strMTB & strMachineID
.Size = New Size(918, 150)
.Location = New Point(startpointX, startpointY)
.BackColor = Color.White
End With
With MachineName
.Name = "lbl" & strMTB & strMachineID
.Text = strMTB & Chr(32) & strMachineID
.Font = New Font("Bookman Old Style", 26, FontStyle.Bold)
.Location = New Point(0, 0) '<- In relation to MachinePanel.ClientRectangle
.AutoSize = True
End With
With MachineStatus
.Name = "lbl" & strMTB & strMachineID & "status"
.Text = "?Unknown?"
.Font = New Font("Bookman Old Style", 22.2, FontStyle.Bold)
.Location = New Point(0, 30)
.AutoSize = True
.Enabled = True
.Visible = True
End With
With RunningProg
.Name = "lbl" & strMTB & strMachineID & "prog"
.Text = "prog????"
.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
.Location = New Point(0, 60)
.AutoSize = True
End With
With RunningPart
.Name = "lbl" & strMTB & strMachineID & "part"
.Text = "part????"
.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
.Location = New Point(0, 90)
.AutoSize = True
End With
With PartsComplete
.Name = "lbl" & strMTB & strMachineID & "complete"
.Text = "complete????"
.Font = New Font("Bookman Old Style", 12, FontStyle.Bold)
.Parent = MachinePanel
.Location = New Point(0, 120)
.AutoSize = True
End With
MachinePanel.Controls.AddRange(New Control() {MachineName, MachineStatus, RunningProg, RunningPart, PartsComplete})
Me.Controls.Add(MachinePanel)
startpointY = startpointY + 150
End While