TableLayoutPanel add Controls not visible - vb.net

I am trying to dynamically add images to a TableLayoutPanel. The add appears to work, when I look at the contents of the control, the new items appear to have been added. The RowCount = 10, the IEnumerable has 18 items that contain the controls I have added.
My problem is, is that when the form is shown, only the first row is visible. I cannot dynamically set the Visible property to True on anything, the instruction is ignored. What am I missing?
Code:
Private Sub LoadTable()
' get the width in pixels of the columns
Dim oSizeType As SizeType = TableLayoutPanel1.ColumnStyles(0).SizeType
Dim Width As Single
Select Case oSizeType
Case SizeType.Percent, SizeType.AutoSize
Width = TableLayoutPanel1.Width / TableLayoutPanel1.ColumnCount
Case SizeType.Absolute
Width = TableLayoutPanel1.ColumnStyles(0).Width
End Select
' Fix the height of the rows
Dim Height As Single = Width
Dim oPicture As New PictureBox
Dim Cols As Integer = 1
Dim Rows As Integer = -1
Dim Cell As String = String.Empty
' loop through all the images from the folder
For i As Integer = 0 To m_FileList.Count - 1
' establish the current row/column in the table
Dim j As Integer = i + 1
'MsgBox(Fix(j / 2))
If Fix(j / 2) <> CDbl(j / 2) Then
Cols = 0
Rows += 1
' add a row if we have moved to the next row
If Rows > 0 Then TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Absolute, Height))
' this doesn't happen automatically
TableLayoutPanel1.RowCount = Rows + 1
Else
Cols = 1
End If
' this is used for the name of some controls
Cell = "R" & Rows & "C" & Cols
' now scale the image to fit into the Table Cells
Dim oPictureBox As New PictureBox
oPictureBox.Height = Height
oPictureBox.Width = Width
Dim oImage As Bitmap = New Bitmap(Bitmap.FromFile(CType(m_FileList.Item(i).Value, String)))
' set the PictureBox properties
oPictureBox.BackgroundImageLayout = ImageLayout.Stretch
oPictureBox.BorderStyle = BorderStyle.Fixed3D
' scale the image to the PictureBox size
'Dim oResized As Image = New Bitmap(Bitmap.FromFile(CType(oPictureBox.Tag, String)))
'ImageEdit.ResizeImage(oImage, oResized, picEnlargement.Width, picEnlargement.Height, False)
ScaleImage(oPictureBox, oImage)
' set the Image of the PictureBox
oPictureBox.Image = oImage
oPictureBox.Name = "PictureBox" & i
' get the path of the current file
Dim f As String = m_FileList(i).Value
'set the properties of the new controls
Dim t As String = GetTitle(f)
'oLabel.Text = t
'oLabel.AutoSize = True
'oLabel.Location = New System.Drawing.Point(30, 110)
oPicture = New PictureBox
With oPicture
SetToolTip(oPicture, f)
oPicture.Tag = f
.Image = oPictureBox.Image
.Dock = DockStyle.Fill
.Size = New System.Drawing.Size(100, 100)
.SizeMode = PictureBoxSizeMode.StretchImage
.Location = New System.Drawing.Point(2, 2)
.Cursor = Cursors.Hand
.Name = "PictureBox" & i + 1
.Visible = True
End With
'here we add the controls to a layout panel to
'manage the positioning of the controls
Dim oContainer As New Panel
With oContainer
.Dock = DockStyle.Fill
.Margin = New System.Windows.Forms.Padding(0)
.Controls.Add(oPicture)
'.Controls.Add(oLabel)
.MaximumSize = New Size(Height, Width)
.MinimumSize = New Size(Height, Width)
.Name = "Container_" & Cell
.Visible = True
End With
' add the
TableLayoutPanel1.Controls.Add(oContainer, Cols, Rows)
'TableLayoutPanel1.SetRow(oContainer, Rows)
'TableLayoutPanel1.SetColumn(oContainer, Cols)
TableLayoutPanel1.Controls.Item(i).Name = "Control_" & Cell
TableLayoutPanel1.Controls.Item(i).Enabled = True
TableLayoutPanel1.Controls.Item(i).Visible = True
'here we add a handler for the picture boxs click event
AddHandler oPicture.Click, AddressOf oPictureClickEvent
Next
TableLayoutPanel1.Visible = True
For i As Integer = 0 To TableLayoutPanel1.Controls.Count - 1
TableLayoutPanel1.Controls(i).Enabled = True
TableLayoutPanel1.Controls(i).Visible = True
Next
End Sub

What was missing was setting the TableLayoutPanel Height. After adding the controls, you need to adjust the Height of the table to a multiple of the height of the rows * (number of rows - 1), that's the basic requirement, but needs a tweak to stop the last row being stretched...
Private Sub LoadTable()
Dim oPictures As Control() = {}
'Dim oTableLayoutPanel As New TableLayoutPanel
' get the width in pixels of the columns
Dim oSizeType As SizeType = TableLayoutPanel1.ColumnStyles(0).SizeType
Dim Width As Single
Select Case oSizeType
Case SizeType.Percent, SizeType.AutoSize
Width = TableLayoutPanel1.Width / TableLayoutPanel1.ColumnCount
Case SizeType.Absolute
Width = TableLayoutPanel1.ColumnStyles(0).Width
End Select
' Fix the height of the rows
Dim Height As Single = Width
Dim oPicture As New PictureBox
Dim Cols As Integer = 1
Dim Rows As Integer = -1
Dim Cell As String = String.Empty
TableLayoutPanel1.RowCount = Fix(m_FileList.Count / 2)
' loop through all the images from the folder
For i As Integer = 0 To m_FileList.Count - 1
' establish the current row/column in the table
Dim j As Integer = i + 1
'MsgBox(Fix(j / 2))
If Fix(j / 2) <> CDbl(j / 2) Then
Cols = 0
Rows += 1
' add a row if we have moved to the next row
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Absolute, Height))
' this doesn't happen automatically
TableLayoutPanel1.RowCount = Rows + 1
Else
' this line should never be needed but just in case
If Rows < 0 Then Rows = 0
Cols = 1
End If
' this is used for the name of some controls
Cell = "R" & Rows & "C" & Cols
'--------------------------------------------
' set up the PictureBox
'--------------------------------------------
Dim oPictureBox As New PictureBox
' get the path of the current file
Dim f As String = m_FileList(i).Value
'set the properties of the new controls
Dim t As String = GetTitle(f)
' create the PictureBox
With oPictureBox
.Height = Height
.Width = Width
' load the image from the current file path
Dim oImage As Bitmap = New Bitmap(Bitmap.FromFile(CType(m_FileList.Item(i).Value, String)))
' set the PictureBox properties
.BackgroundImageLayout = ImageLayout.Stretch
.BorderStyle = BorderStyle.Fixed3D
' scale the image to the PictureBox size
ScaleImage(oPictureBox, oImage)
' set the Image of the PictureBox
.Image = oImage
.Name = "PictureBox" & i + 1
.Dock = DockStyle.Fill
.Size = New System.Drawing.Size(Height, Width)
.SizeMode = PictureBoxSizeMode.StretchImage
.Location = New System.Drawing.Point(0, 0)
.Cursor = Cursors.Hand
.Visible = True
.Enabled = True
' set the Tag to the filepath of the image
.Tag = f
' set the ToolTip for the PictureBox
' This becomes the "Title" from the File MetaData
SetToolTip(oPictureBox, f)
'here we add a handler for the PictureBox click event
AddHandler oPictureBox.Click, AddressOf PictureClickEvent
End With
oPictures.Add(oPictureBox)
Next
' now add the picturebox to the next cell addres
With TableLayoutPanel1
' add the
.Controls.AddRange(oPictures)
'.Controls.Add(oPictureBox, Cols, Rows)
'.SetRow(oPictureBox, Rows)
'.SetColumn(oPictureBox, Cols)
'.Controls.Item(i).Name = "Control_" & Cell
'.Controls.Item(i).Enabled = True
'.Controls.Item(i).Visible = True
End With
TableLayoutPanel1.Visible = True
For i As Integer = 0 To TableLayoutPanel1.Controls.Count - 1
TableLayoutPanel1.Controls(i).Enabled = True
TableLayoutPanel1.Controls(i).Visible = True
Next
' adjust the height of the table to a multiple of the number of new rows * the Height of each row
TableLayoutPanel1.Height = (TableLayoutPanel1.RowCount - 1) * Height
' set the TableLayoutPanel properties
TableLayoutPanel1.Dock = DockStyle.Top
TableLayoutPanel1.AutoSize = False
TableLayoutPanel1.Visible = True
TableLayoutPanel1.Enabled = True
TableLayoutPanel1.Focus()
TableLayoutPanel1.Parent = Me.Panel1
End Sub

Related

As population increases the SIR model graph should shift left. And the recovery & transmission rate trackbars don't work at all

I'm trying to simulate the spread of a virus using the SIR model in VB.net but my code doesn't work.
increase initial infections: should shift graph left (but mine doesn't)
increase Population: shifts graph left (but mine doesn't)
increase Susceptible: shifts graph left (but mine doesn't)
increase transmission rate (b): increases peak of 'infectives' curve (but my trackbar doesn't work at all - produces an overflow error)
increase recovery rate (a): 'infectives' peak decreases, while the other two lines go up
This is what the graph should do: https://faradars.org/ev/sir-simulator/?lang=en
These images demonstrate the errors in my code that I don't know how to fix:
Here's my code:
Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'initail values
Dim N As Double = 10000
Dim S As Double = 8000
Dim R = 0.0
Dim I As Double = N - S - R
Dim t As Double = 0
Dim b As Double = 2 'contact rate
Dim a As Double = 0.5 'removal rate
Dim scale As Double = 0.1
setupForm(N, S, I, R, t, b, a, scale)
ProccessGraph()
End Sub
Sub setupForm(N, S, I, R, t, b, a, scale)
'Trackbars
Dim tbData(7) As Decimal
tbData(1) = N 'population N
tbData(2) = S 'Susceptibles S
tbData(3) = I 'infectives I
tbData(4) = R 'Recoveries R
tbData(5) = t 'time t
tbData(6) = b 'infection rate b
tbData(7) = a 'removal rate a
Dim y As Integer = 10
For I = 1 To 7
Dim Tbar As New TrackBar
With Tbar
.Location = New Point(20, y)
.Size = New Size(140, 30)
.BackColor = Color.White
.Minimum = 0
.Maximum = 10000
.SmallChange = 1
.Name = "Trackbar" & I
.Value = tbData(I)
End With
Me.Controls.Add(Tbar)
'labels (display value) ✓
Dim labvalue As New Label
With labvalue
.Location = New Point(180, y)
.Name = "label" & I
.Size = New Size(50, 15)
End With
Me.Controls.Add(labvalue)
'labels (tbar title) ✓
Dim labtitle_data(7) As String
labtitle_data(1) = "Population N"
labtitle_data(2) = "Susceptibles S"
labtitle_data(3) = "Infectives I"
labtitle_data(4) = "Recoveries R"
labtitle_data(5) = "time"
labtitle_data(6) = "infection rate"
labtitle_data(7) = "removal rate"
Dim labtitle As New Label
With labtitle
.Location = New Point(240, y)
.Name = "label" & I
.Size = New Size(60, 60)
.Text = labtitle_data(I)
End With
y += 60
Me.Controls.Add(labtitle)
'ComboBox (to list countries) ✓
Dim cb1 As New ComboBox
cb1.Items.Add("China")
cb1.Location = New Point(990, 50)
Me.Controls.Add(cb1)
'Form properties ✓
Me.Size = New Size(1200, 500)
Me.BackColor = Color.White
AddHandler Tbar.ValueChanged, AddressOf ProccessGraph 'every time the value changes, recreate the graph to match it
Next
End Sub
Sub ProccessGraph()
Dim tblist(7) As TrackBar 'array of trackbars
For tbar = 1 To 7
tblist(tbar) = Me.Controls("TrackBar" & tbar)
Me.Controls("label" & tbar).Text = tblist(tbar).Value 'adds value to label
Next
'reset NSIR values to match trackbar values
Dim N = tblist(1).Value
Dim S = tblist(2).Value
Dim I = tblist(3).Value
Dim R = tblist(4).Value
Dim t = tblist(5).Value
Dim b = tblist(6).Value
'Dim a = tblist(7).Value
Dim a As Double = 0.5
Dim scale As Double = 0.1
'b = tblist(6).Value
'a = tblist(7).Value
'chart lines ✓
Chart1.Series.Clear()
Chart1.Titles.Clear()
Dim serS As New Series
Dim serI As New Series
Dim serR As New Series
serS.Name = "S"
serS.ChartType = SeriesChartType.Line
serS.BorderWidth = 2
serI.Name = "I"
serI.ChartType = SeriesChartType.Line
serI.BorderWidth = 2
serR.Name = "R"
serR.ChartType = SeriesChartType.Line
serR.BorderWidth = 2
'chart calculations ✓
For ind = 0 To 99
serS.Points.AddXY(t, S)
serI.Points.AddXY(t, I)
serR.Points.AddXY(t, R)
Dim ds = (-b * S * I) / N
Dim Di = ((b * S * I) / N) - a * I
Dim Dr = a * I
Dim dt = 1
S = S + ds * scale
I = I + Di * scale
R = R + Dr * scale
t = t + dt * scale
Next
'chart properties ✓
Chart1.Series.Add(serS)
Chart1.Series.Add(serI)
Chart1.Series.Add(serR)
Chart1.ChartAreas("ChartArea1").AxisX.Title = "Days"
Chart1.ChartAreas("ChartArea1").AxisY.Title = "Population"
Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
Chart1.ChartAreas("ChartArea1").AxisY.Interval = 500
Chart1.Titles.Add("SIR Graph")
Chart1.Location = New Point(280, 30)
Chart1.Size = New Size(700, 400)
''trackbar colors which, remember, are only accessible via the array tbs
'tblist(1).BackColor = Color.LightGray
'tblist(2).BackColor = Color.Blue
'tblist(3).BackColor = Color.Yellow
'tblist(4).BackColor = Color.LightCoral
End Sub
End Class`
Existing SIR models:
https://faradars.org/ev/sir-simulator/?lang=en
Existing SIR models code:
https://www.google.com/amp/s/jamesmccaffrey.wordpress.com/2020/02/11/the-kermack-mckendrick-sir-disease-model-using-c/amp/
https://github.com/henrifroese/infectious_disease_modelling/blob/master/part_two.ipynb

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.

How to print loop result in next blank page if Current Page is Full

I have have the following codes to print the voucher, but I face problem in loop section while printing the SQL query result if the page is full it reprints using same page.
enter image description here
Private Sub ATATprint_PrintPage(sender As Object, e As PrintPageEventArgs) Handles ATATprint.PrintPage
Dim Brush1 As New SolidBrush(Color.Black)
Dim ValueBrush As New SolidBrush(Color.DarkGreen)
Dim lblFont As Font = New Font("B Yekan", 10, FontStyle.Regular)
Dim ValueFont As Font = New Font("Agency FB", 10, FontStyle.Bold)
Dim ypos As Integer = 300
Dim pn As Integer = 1
Dim str(6) As String
str(0) = TrnAccountType
str(1) = TrnAccountNo
str(2) = TrnAccountName
str(3) = TrnCurrecy
str(4) = TrnExRate
str(5) = TrnAmount
str(6) = TrnNarration
Try
Dim adapter As New SqlDataAdapter("select case when trd_DrCr = 'Dr' then 'Debit' else 'Credit' end,
isnull(acc_Ccy, '')+'-'+Convert(nvarchar,trd_Account), acc_Name, trd_ccy, format(trd_ExRate,'#,###,###.0000'), format(trd_Amount, '#,###,###.00'), trd_Narration
from TransactionDetails join Accounts on Accounts.acc_Number = TransactionDetails.trd_Account where trd_TrnRef = '" & fncTrnReference.Text & "'", connection)
Dim table As New DataTable
adapter.Fill(table)
For row As Integer = 0 To table.Rows.Count - 1
For col As Integer = 0 To table.Columns.Count - 1
e.Graphics.DrawString(str(col), lblFont, Brush1, 100, ypos)
e.Graphics.DrawString(table.Rows(row)(col).ToString, ValueFont, ValueBrush, 200, ypos)
ypos += 15
Next
ypos += 30
If ypos > 900 Then
ypos = 200
e.HasMorePages = True
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
e.HasMorePages = False
End Sub
You need to fill the adapter outside of the PrintPage method and also keep track of the value of the row variable from your for loop. When the PrintPage method is called again, start your For loop from that point.
Also, you don't need to create new SolidColorBrushes if you are using the standard colors.
Finally, be sure to dispose your Fonts when finished. I did this in the Finally block of the code below.
This code is not tested so it may require some changes to meet your needs, but it should give you some ideas.
'These variables are declared outside the PrintPage method so they retain their values between calls.
Private adapter As SqlDataAdapter = Nothing
Private savedRowValue As Integer = 0
Private table As DataTable = Nothing
Private Sub ATATprint_PrintPage(sender As Object, e As PrintPageEventArgs) Handles ATATprint.PrintPage
Dim Brush1 As Brushes.Black 'Use the standard brushes here.
Dim ValueBrush Brushes.DarkGreen
Dim lblFont As Font = New Font("B Yekan", 10, FontStyle.Regular)
Dim ValueFont As Font = New Font("Agency FB", 10, FontStyle.Bold)
Dim ypos As Integer = 300
Dim pn As Integer = 1
Dim str(6) As String
str(0) = TrnAccountType
str(1) = TrnAccountNo
str(2) = TrnAccountName
str(3) = TrnCurrecy
str(4) = TrnExRate
str(5) = TrnAmount
str(6) = TrnNarration
Try
'Create the data adapter and fill the DataTable only on the first time the PrintPage method is called
If adapter Is Nothing Then
adapter As New SqlDataAdapter("select case when trd_DrCr = 'Dr' then 'Debit' else 'Credit' end,
isnull(acc_Ccy, '')+'-'+Convert(nvarchar,trd_Account), acc_Name, trd_ccy, format(trd_ExRate,'#,###,###.0000'), format(trd_Amount, '#,###,###.00'), trd_Narration
from TransactionDetails join Accounts on Accounts.acc_Number = TransactionDetails.trd_Account where trd_TrnRef = '" & fncTrnReference.Text & "'", connection)
table = New DataTable
adapter.Fill(table)
End If
'Start the For loop at the saved value instead of at 0
For row As Integer = savedRowValue To table.Rows.Count - 1
For col As Integer = 0 To table.Columns.Count - 1
e.Graphics.DrawString(str(col), lblFont, Brush1, 100, ypos)
e.Graphics.DrawString(table.Rows(row)(col).ToString, ValueFont, ValueBrush, 200, ypos)
ypos += 15
Next
ypos += 30
If ypos > 900 Then
ypos = 200
e.HasMorePages = True
savedRowValue = row + 1 'Save the value of the current row
Exit Sub
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
lblFont.Dispose() 'Dispose of your fonts here
ValueFont.Dispose()
End Try
e.HasMorePages = False
End Sub

Runtime datagridview

I want to design datagridview at run time I want it to fill with data and appear on the form according to comboboxtext and if combobox is empty it disappear and when I click on datagridview I want the cell to be selectedvalue in the combobox and datagriddisapear
And here the code that I tried
Private Sub ComDr_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComDr.KeyPress
Dim d As New DataGridView
Dim dt As DataTable = New DAL().selectdatatable(String.Format("select Dr_Name,Dr_No from DR where Dr_Name like '%{0}%'", ComDr.Text))
If dt.Rows.Count > 0 Then
' Try
Controls.Add(d)
d.DataSource = dt
d.BringToFront()
With d
.Name = "Dr_Name"
.Width = ComDr.Width
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.ColumnHeadersHeight = 30
.Height = 10 * 35
.ForeColor = Color.Blue
.BackgroundColor = Color.Beige
.RowHeadersVisible = False
.BackgroundColor = Color.BurlyWood
'.DefaultCellStyle.SelectionForeColor = Color.Yellow
' .DefaultCellStyle.SelectionForeColor = Color.Black
' .DefaultCellStyle.Font = New Font("tahoma", 13)
.Location = New System.Drawing.Point(680, ComDr.Location.Y + 30)
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
End With
For i As Integer = 0 To d.Rows.Count - 1
Dim row As DataGridViewRow = d.Rows(i)
row.Height = 35
d.Rows(i).DefaultCellStyle.BackColor = If(i Mod 2 = 0, Color.Wheat, Color.BurlyWood)
Next
AddHandler d.CellClick, AddressOf d_cellclick
'ComDr.DisplayMember = d(0, d.SelectedRows(0).Index).Value.ToString
'ComDr.ValueMember = d(1, d.SelectedRows(0).Index).Value.ToString
'ComDr.Text = String.Empty
'Controls.Remove(d)
' ComDr.SelectedValue = d(0, d.SelectedRows(0).Index).Value.ToString
'Catch ex As Exception
'MsgBox(ex.Message)
'End Try
' Controls.Remove(d)
End If
End Sub

create labels on a form taken from cells in a datagridview on another form vb.net

I have a datagridview on a form with 6 columns and an undetermined number of rows. The user is entering values into this datagridview. I would now like to create an invoice based on the entries in the datagridview. I am creating this invoice on another form. Unfortunately, the values in the cells are not showing up with the code I have. This is the code located in the Invoice class.
Dim lbl(5) As Label
For Each row As DataGridViewRow In Main.DataGridView1.Rows
If Not row.IsNewRow Then
Dim x As Integer = 0
For Each col As DataGridViewColumn In Main.DataGridView1.Columns
i = row.Index
j = col.Index
With lbl(x)
.AutoSize = True
.BackColor = System.Drawing.SystemColors.Control
.Font = New Font(lbl(x).Font.FontFamily, 8.45, FontStyle.Regular)
.ForeColor = System.Drawing.SystemColors.ControlText
.Location = New System.Drawing.Point(i * 111 + 6, (i + 1) * 24 + 16)
.Text = Main.DataGridView1.Rows(i).Cells(j).Value
End With
MsgBox(lbl(x).Text)
GroupBoxInvoiceInvoice.Controls.Add(lbl(x))
x += 1
Next
End If
Next
Any help would be greatly appreciated!
Here is the new block of code.
Dim Label1, Label2, Label3, Label4, Label5, Label6 As New Label
Dim lbl() As Control = {Label1, Label2, Label3, Label4, Label5, Label6}
Dim val() As String = {"Date", "Category", "Description", "Units", "Rate", "Amount"}
For Each row As DataGridViewRow In Main.DataGridView1.Rows
If Not row.IsNewRow And i < Main.DataGridView1.Rows.Count Then
Dim x As Integer = 0
For Each col As DataGridViewColumn In Main.DataGridView1.Columns
i = row.Index
j = col.Index
With lbl(x)
.AutoSize = True
.BackColor = System.Drawing.SystemColors.Control
.Font = New Font(lbl(x).Font.FontFamily, 8.45, FontStyle.Regular)
.ForeColor = System.Drawing.SystemColors.ControlText
.Location = New System.Drawing.Point(j * 111 + 6, (i + 1) * 24 + 16)
.Text = Main.DataGridView1.Rows(i).Cells(j).Value
End With
GroupBoxInvoiceInvoice.Controls.Add(lbl(x))
x += 1
j += 1
Next
i += 1
j = 0
x = 0
End If
Next
Thank you, Plutonix!! You're help has been awesome and greatly appreciated! You have shown much patience, also! Here is the final portion of code that worked for me based off of what you had shown below. Thanks again!!
i = 0
For Each row As DataGridViewRow In Main.DataGridView1.Rows
If Not row.IsNewRow Then
For c As Integer = 0 To row.Cells.Count - 3
Dim lbl As New Label
With lbl
.AutoSize = True
.BackColor = System.Drawing.SystemColors.Control
.Font = New Font(lbl.Font.FontFamily, 8.45, FontStyle.Regular)
.ForeColor = System.Drawing.SystemColors.ControlText
.Location = New System.Drawing.Point(c * 111 + 6, (i + 1) * 24 + 16)
.Text = row.Cells(c).Value.ToString
End With
GroupBoxInvoiceInvoice.Controls.Add(lbl)
Console.WriteLine("label {0}", row.Cells(c).Value.ToString)
Next
End If
i += 1
Next
You have 1 or 2 problems with your loop.
Dim lbl(5) As Label
This declares you plan to make an array of labels, but you never initialize it. When I try to run your code (w/o dgv) it crashes because there is nothing in lbl(x) ('Object reference not set to an instance of an object.'). There is no reason to stash the labels in an array if they are going to be added to a form. So, just create labels as you need them:
For Each col As DataGridViewColumn In Main.DataGridView1.Columns
i = row.Index
j = col.Index
Dim lbl As New Label ' make a new label
With lbl
.AutoSize = True
.BackColor = System.Drawing.SystemColors.Control
.Font = New Font(lbl(x).Font.FontFamily, 8.45, FontStyle.Regular)
.ForeColor = System.Drawing.SystemColors.ControlText
' the above props are being set to default values, so arent really needed
.Location = New System.Drawing.Point(i * 111 + 6, (i + 1) * 24 + 16)
' I think this needs to be changed:
.Text = Main.DataGridView1.Rows(i).Cells(j).Value.ToString
End With
MsgBox(lbl(x).Text)
GroupBoxInvoiceInvoice.Controls.Add(lbl)
x += 1
Next
This worked fine without the dgv reference, so if the labels are still blank, check to make sure there is something in those cells to display. If that loop was executing all the way something somewhere was eating the exception and could be eating another.
-------------------- EDIT ----------------------------
The problem is using row.index and col.index as for i,j. Those have to do with databands and return 0 otherwise. You want to loop thru the CELLS for each row:
For Each row As DataGridViewRow In dgv.Rows
If row.IsNewRow = False Then
' loop thru cells in row
For c As Integer = 0 To rrow.Cells.Count - 1
Dim lbl As New Label
With lbl
.AutoSize = True
.BackColor = System.Drawing.SystemColors.Control
.BorderStyle = BorderStyle.Fixed3D
.ForeColor = System.Drawing.SystemColors.ControlText
.Location = New System.Drawing.Point(r + 5, c * 22) ' FIX
' CONVERT value TO STRING!!!
.Text = rrow.Cells(c).Value.ToString
End With
Panel1.Controls.Add(lbl)
' prints as many time as there are labels/cells
Console.WriteLine("label {0}", rrow.Cells(c).Value.ToString)
Next
End If
Next
Console.WriteLine("{0}", Panel1.Controls.Count) ' my locations are foobar
' but the right number are there.
You will want to add r,c (or i, j) counters for positioning the labels on the form, but otherwise, all is well in LabelLand...of should be