I'm trying to create a list of labels and textboxes. No errors but they aren't rendering on the form. I have confirmed my loop have values
Private Sub AddLabels_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'MsgBox(strNumberOfLabels + " " + strOrderNum)
TableLayoutPanel1.AutoSize = True
TableLayoutPanel1.Visible = False
TableLayoutPanel1.SuspendLayout()
For i As Integer = 0 To strNumberOfLabels
'MsgBox(i)
Dim txtBox As New TextBox
Dim txtLabel As New Label
txtLabel.Text = "Label " + i
txtBox.Name = "txt" + i
TableLayoutPanel1.Controls.Add(txtLabel)
txtLabel.Show()
txtBox.Show()
TableLayoutPanel1.ResumeLayout()
TableLayoutPanel1.Visible = True
Next
End Sub
Try using the other Add overload, which specifies which column and row the control should go into:
Dim txtLabel As New Label
txtLabel.Text = "Label" + i.ToString
'\\ TableLayoutPanel1.Controls.Add(txtLabel)
TableLayoutPanel1.Controls.Add(txtLabel, 0, 0)
This is not necessary:
'\\ txtLabel.Show()
This should be moved outside of the loop:
Next
TableLayoutPanel1.ResumeLayout()
'\\ TableLayoutPanel1.Visible = True
The txtBox control is never being added to the TableLayoutPanel control or the form.
I don't think it's necessary to make your TableLayoutPanel visible or invisible during the OnLoad procedure, the form isn't visible yet.
The only other thing to confirm is the value of strNumberOfLabels. I'm suspecting it's zero.
Related
I have a Windows Forms Application with an MDIParent Form and Windows Form. The Form has a handful of controls and on Form_Load I add a User Control.
Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim Sample1 As New ucBODSample
With Sample1
.Name = "Sample_1"
.Text = "Sample 1"
.Location = New Point(10, 497)
End With
m_intSampleCount = 1
Me.Controls.Add(Sample1)
End Sub
On Button click, I want to load additional instances of this user control:
Private Sub cmdAddSample_Click(sender As Object, e As EventArgs) Handles cmdAddSample.Click
m_intSampleCount = m_intSampleCount + 1
Dim y_uc As Integer
Dim y_b As Integer
Dim y_Me As Integer
If Me.Height <> 910 Then
y_Me = 910
Me.Height = y_Me
Me.Width = Me.Width + 15
Me.HorizontalScroll.Maximum = 0
Me.AutoScroll = True
End If
Dim SampleX As New ucBODSample
With SampleX
.Name = "Sample_" & m_intSampleCount
.Text = "Sample " & m_intSampleCount
.grbSample.Text = "Sample " & m_intSampleCount
y_uc = 317 + (m_intSampleCount * 175)
.Location = New Point(10, y_uc)
End With
y_b = 495 + (m_intSampleCount * 175)
Me.Controls.Add(SampleX)
Me.cmdAddSample.Location = New Point(10, y_b)
End Sub
The Native Height of the Form is 754. On the first button click, the height of the form is set to 910 and the width of the form is increase by 15 and the "Sample 2" UserControl adds as expected.
On the second button click, the scroll bar appears and the "Sample 3" UserControl adds as expected and we auto scroll to the bottom of the form.
On the third button click, the "Sample 4" UserControl adds, but there is a large gap between it and the previous user control.
On subsequent button clicks, the "Sample X" UserControl adds, but the gap between user controls keeps getting wider and wider.
When "Sample 3" UserControl is added, the y coordinate is 842 (less than 910, the height of the form). "Sample 4" is the first control added where the y coordinate is greater than the height of the form and it is also the first one mispositioned.
The AddSample Button is always at the bottom of the form, the appropriate distance from the last added user control.
How should I adjust the code to continue to stack instances of this user control tightly, even after I have exceeded the height of the form?
I added the following code to resolve the issue:
If y_uc > 842 Then
y_uc = y_uc - Me.VerticalScroll.Value
End If
If y_b > 1020 Then
y_b = y_b - Me.VerticalScroll.Value
End If
The y position is based on the top of the form. And since the form has numerous controls scrolled above the top of the form, the 0 of y has changed.
UPDATE: I removed the if and just set y_uc = y_uc - Me.VerticalScroll.Value because until it scrolls, the Me.VerticalScroll.Value = 0.
First we need to find the location of the last control that was added, then add the height of the UserControl (ucBODSample).
Dim yLoc As Integer = Me.Controls.OfType(Of ucBODSample).LastOrDefault().Location.Y + 317
Next we use that as the Y location for the new UserControl.
Dim SampleX As New ucBODSample
With SampleX
.Name = "Sample_" & m_intSampleCount
.Text = "Sample " & m_intSampleCount
.Title = "Sample " & m_intSampleCount
y_uc = yLoc '317 + (m_intSampleCount * 175)
.Location = New Point(10, y_uc)
End With
Lastly we need to adjust the button's location.
y_b = SampleX.Location.Y + SampleX.Height + cmdAddSample.Height
Put it all together and we get
Private Sub cmdAddSample_Click(sender As Object, e As EventArgs) Handles cmdAddSample.Click
Dim y_b As Integer = 0
If Me.Height <> 910 Then
Me.Height = 910
Me.Width = Me.Width + 15
Me.HorizontalScroll.Maximum = 0
Me.AutoScroll = True
End If
'' Find the last control on the Form of type ucBODSample. Get the location of Y. Location Y is
'' only the starting point of the Y axis on the user control. Since we need the location of the
'' bottom of the control we add the height of the user control to the Y location. We're using
'' 317 as a constant value for height. I'd recommend using the height of the control instead.
'' Leaving as is for simplicity.
Dim yLoc As Integer = Me.Controls.OfType(Of ucBODSample).LastOrDefault().Location.Y + 317
'' Create an instance of the user control and set its location using the found value for Y axis.
Dim SampleX As New ucBODSample
With SampleX
.Name = "Sample_" & m_intSampleCount
.Text = "Sample " & m_intSampleCount
.Title = "Sample " & m_intSampleCount '' changed grbSample.Text for a property on ucBODSample
.Location = New Point(10, yLoc)
End With
'' Since the button should always be at the bottom we use the location of the user control that
'' was just added and add the height of the user control and the button.
y_b = SampleX.Location.Y + SampleX.Height + cmdAddSample.Height '495 + (m_intSampleCount * 175)
Me.Controls.Add(SampleX)
Me.cmdAddSample.Location = New Point(10, y_b)
End Sub
Property on User Control (ucBODSample)
Public Property Title As String
Get
Return grbSample.Text
End Get
Set(value As String)
grbSample.Text = value
Me.Invalidate()
End Set
End Property
So I am making a function that will populate the TableLayoutPanel from FileDialog Result then make a delete button for each row using a loop. Here's the code
Private PathtoFile1 As New List(Of String) 'this will contain all the selected file in the dialogwindow
Private rowLineDrawing As Integer = 0
Private selectedfilecountLineDrawing As Integer
Public Function AttachFileLineDrawing(TLP As TableLayoutPanel)
Dim dr = OpenFileDialog1.ShowDialog
If (dr = System.Windows.Forms.DialogResult.OK) Then
selectedfilecountLineDrawing = OpenFileDialog1.FileNames.Count
For Each FileName In OpenFileDialog1.FileNames
Try
Console.WriteLine(FileName.ToString)
PathtoFile1.Add(FileName.ToString)
Catch SecEx As Security.SecurityException
MessageBox.Show("Security error. Please contact your administrator for details.\n\n" &
"Error message: " & SecEx.Message & "\n\n" &
"Details (send to Support):\n\n" & SecEx.StackTrace)
Catch ex As Exception
'Could Not Load the image - probably permissions-related.
MessageBox.Show(("Cannot display the image: " & FileName.Substring(FileName.LastIndexOf("\"c)) &
". You may not have permission to read the file, or " + "it may be corrupt." _
& ControlChars.Lf & ControlChars.Lf & "Reported error: " & ex.Message))
End Try
Next
'MAKE SOMETHING HERE TO DISPLAY THE SELECTED ITEMS IN THE TABLELAYOUTPANEL OF THE SUBMIT PROGRESS
TLP.Controls.Clear()
TLP.RowCount = 0
rowLineDrawing = 0
For Each Path In PathtoFile1
Dim filepath As New Label
filepath.Text = Path
filepath.Width = Val(360)
'this button is for previewing the file
Dim btnPreview As New Button
AddHandler btnPreview.Click,
Sub(s As Object, e As EventArgs)
Dim btn = CType(s, Button)
MsgBox("This is Preview")
End Sub
'This button is for removing rows in the tablelayoutpanel
Dim btnRmv As New Button
Dim StringToIndex As String = Path 'THIS CATCHES EVERY PATH IN THE LOOP AND STORE IT TO THE VARIABLE WHICH THEN BE USED AS A COMPARABLE PARAMETER FOR THE INDEX SEARCH
Dim index = PathtoFile1.IndexOf(Path)
AddHandler btnRmv.Click,
Sub(s As Object, e As EventArgs)
Dim btn = CType(s, Button)
MsgBox(index)
PathtoFile1.RemoveAt(index) 'THIS LINE OF CODE REMOVE THE SPECIFIC ITEM IN THE LIST USING THE BTNRMV CLICK
'MAKE SOMETHING HERE TO REMOVE THE ROW IN THE TABLELAYOUTAPANEL
End Sub
TLP.SuspendLayout()
TLP.RowStyles.Add(New RowStyle(SizeType.Absolute, 20))
TLP.Controls.Add(filepath, 0, rowLineDrawing)
TLP.Controls.Add(btnPreview, 1, rowLineDrawing)
TLP.Controls.Add(btnRmv, 2, rowLineDrawing)
TLP.ResumeLayout()
rowLineDrawing -= -1
Next
End If
End Function
So I am trying to remove the row in the TableLayoutPanel together with the dynamic control. My approach is removing the selected item in the list and I achieved it properly but can't remove the row in the TableLayoutPanel. Any help is much appreciated!
EDIT
I have tried to use the provided module above but got this error
And got this error
Here is an extension method that will enable you to remove any row from a TableLayoutPanel by index:
Imports System.Runtime.CompilerServices
Public Module TableLayoutPanelExtensions
<Extension>
Public Sub RemoveRowAt(source As TableLayoutPanel, index As Integer)
If index >= source.RowCount Then
Throw New ArgumentOutOfRangeException(NameOf(index),
index,
"The row index must be less than the number of rows in the TableLayoutPanel control.")
End If
'Remove the controls in the specified row.
For columnIndex = 0 To source.ColumnCount - 1
Dim child = source.GetControlFromPosition(columnIndex, index)
If child IsNot Nothing Then
child.Dispose()
End If
Next
'Move controls below the specified row up.
For rowIndex = index + 1 To source.RowCount - 1
For columnIndex = 0 To source.ColumnCount - 1
Dim child = source.GetControlFromPosition(columnIndex, rowIndex)
If child IsNot Nothing Then
source.SetCellPosition(child, New TableLayoutPanelCellPosition(columnIndex, rowIndex - 1))
End If
Next
Next
'Remove the last row.
source.RowCount -= 1
End Sub
End Module
I tested that on 3 column by 4 row TableLayoutPanel containing a Label in each cell executing the following code twice:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TableLayoutPanel1.RemoveRowAt(1)
End Sub
The result was as expected, i.e. removing the second-from-top row each time. You may need to fiddle a bit more depending on what you want to happen row heights. I had the row heights set to equal percentages so the remaining rows grew proportionally to fill the space. If you want something different, you can add code accordingly. Note that you could create an almost identical method for removing columns.
I created a user control with datagridview and label that display the row count. On some of the projects where I used the control, I'm having issue with the CellEnter event where it is not displaying the correct row count. I placed the label.text in the CellEnter event so the label value can change based on the entered cell.
In one of my projects, I have buttons that work as tabs. When the form load, it is adding the new control and populate the data. When button is clicked, it will delete the existing control and add new control (I did this because for some reason the column from previous table stick in the dgv even though I already clear the datatable and set the datasource to nothing). For some of the tables that I binded to the datagridview, the rowcount on the CellEnter display 2 (allow add row is set to true) where as in the DataSourceChange or CellValidating, it is showing the correct number (ex. 664). This only happen on the first load, once moving to different cell, it shows correct value.
So here's the sequence when the form first loaded:
1. CellEnter (row count = 2)
2. DataSourceChanged (row count = 664)
3. CellValidating (row count = 664)
4. CellEnter (row count = 2)
Click button that load the same table as when the form first load:
1. CellEnter (row count = 2)
2. DataSourceChanged (row count = 664)
I tried to use the row count based on the value that I get from the DataSourceChange, but it will messed up the label value if the records get deleted or added.
Also tried to move the label to CellValidating, but it not always display the correct row (Ex: Click cell 664 and move to cell 659, the label still display the 664).
If adding dgv1.dgvEditor.CurrentCell = dgv1.dgvEditor.Item("TAG_CODE", 1) to PopulateCodesGrid, it will display the correct label, but when changing the row to 0, it ended up with 1 of 1.
Private Sub dgvEditor_CellEnter(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvEditor.CellEnter
If AllowUserToAddRow Then
If dgvEditor.CurrentCell.RowIndex = dgvEditor.Rows(dgvEditor.NewRowIndex).Index Then
NewRowIndex = dgvEditor.CurrentCell.RowIndex
lblDataNav.Text = dgvEditor.CurrentCell.RowIndex + 1 & " of " & dgvEditor.RowCount
ElseIf NewRowIndex <> -1 Then
lblDataNav.Text = dgvEditor.CurrentCell.RowIndex + 1 & " of " & dgvEditor.RowCount - 1
Else
lblDataNav.Text = dgvEditor.CurrentCell.RowIndex + 1 & " of " & dgvEditor.RowCount - 1
End If
Else
lblDataNav.Text = dgvEditor.CurrentCell.RowIndex + 1 & " of " & dgvEditor.RowCount
End If
End Sub
Private Sub SystemAdminForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
dgv1 = New SQLTableEditor.ctlTableEditor
Me.Controls.Add(dgv1)
dgv1.BringToFront()
dgv1.Visible = True
dgv1.Location = New Point(25, 115)
dgv1.Size = New Size(722, 550)
dgv1.HeaderLabelVisible = False
dgv1.DataNavigatorVisible = True
PopulateCodesGrid()
End Sub
Private Sub CodesTab_Click(sender As System.Object, e As System.EventArgs) Handles CodesTab.Click
'Button click
If (dgv1 IsNot Nothing) AndAlso (Not dgv1.IsDisposed) Then dgv1.Dispose()
Dim btn As Button = DirectCast(sender, Button)
Select Case btn.Name
Case "CodesTab"
dgv1 = New SQLTableEditor.ctlTableEditor
Me.Controls.Add(dgv1)
dgv1.BringToFront()
dgv1.Visible = True
dgv1.Location = New Point(25, 115)
dgv1.Size = New Size(722, 550)
dgv1.HeaderLabelVisible = False
dgv1.DataNavigatorVisible = True
PopulateCodesGrid()
End Sub
Private Sub PopulateCodesGrid()
Try
Using connection As New SqlClient.SqlConnection(MAIN_CONN)
connection.Open()
Using dAdapt As New SqlClient.SqlDataAdapter("spGetCodes", connection)
Dim colCategory = New DataGridViewComboBoxColumn
colCategory.DataPropertyName = "CATEGORY"
colCategory.HeaderText = "Category"
colCategory.Name = "CATEGORY"
colCategory.Width = 150
colCategory.SortMode = DataGridViewColumnSortMode.Automatic
For Each item In viewModel.DefectCategoryDropDownList
colCategory.Items.Add(item.Value)
Next
dgv1.dgvEditor.Columns.Add(colCategory)
dgv1.AllowUserToAddRow = True
dgv1.AllowUpdateEditRecord = True
dgv1.AllowUserToDeleteRow = False
dgv1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells
dAdapt.Fill(dgv1.dTable)
dgv1.BindingSrc.DataSource = dgv1.dTable
dgv1.dgvEditor.DataSource = dgv1.BindingSrc
dgv1.dgvEditor.Columns("TAG_CODE").DisplayIndex = 0
dgv1.dgvEditor.Columns("TAG_CODE").HeaderText = "CODE"
dgv1.dgvEditor.Columns("TAG_CODE").ReadOnly = True
dgv1.dgvEditor.Columns("PROBLEM").DisplayIndex = 1
dgv1.dgvEditor.Columns("PROBLEM").HeaderText = "Description"
dgv1.dgvEditor.Columns("CATEGORY").DisplayIndex = 2
dgv1.dgvEditor.Columns("INACTIVE_DATE").DisplayIndex = 3
dgv1.dgvEditor.Columns("INACTIVE_DATE").HeaderText = "Inactive Date"
RemoveHandler dgv1.InsertRecord, AddressOf RTCodesInsertRecord
RemoveHandler dgv1.UpdateRecord, AddressOf RTCodesUpdateRecord
RemoveHandler dgv1.CellDefaultValue, AddressOf CellDefaultValue
RemoveHandler dgv1.CellClick, AddressOf DGV1CellClickEvent
AddHandler dgv1.InsertRecord, AddressOf RTCodesInsertRecord
AddHandler dgv1.UpdateRecord, AddressOf RTCodesUpdateRecord
AddHandler dgv1.CellDefaultValue, AddressOf CellDefaultValue
AddHandler dgv1.CellClick, AddressOf DGV1CellClickEvent
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
I expected the rowcount in the CellEnter to be 664, not 2. I had other programmer help me looking at my code, and couldn't figure it out either. Note that this only happen on some, some other table on that same project loads just fine.
I have a setup in my code where there is a datagridview. For each row I have a combo box cell that I have a separate combo box cell since I want a different selection of items for each cell.
Problem : The cell only drops down when the arrow is double clicked. How can I change the cell formatting, or possibly a cell click event, so that the cell response to just one click?
Here's my cell creation code. Frankly, I didn't start any other code since I didn't know what event to touch or call. Is there a property I can edit?
Code:
'add items to combobox list
Dim comboCell As New DataGridViewComboBoxCell
comboCell.FlatStyle = FlatStyle.Flat
Dim resolutionList As New List(Of cmbStruct)
Dim currentResIndex As Integer = 0
'create list of resolutions
For j As Integer = 0 To resolutions.Length - 1
Dim resClass As New cmbStruct
resClass.Name = resolutions(j)
resClass.ID = resolutions(j)
resolutionList.Add(resClass)
comboCell.Items.Add(resolutions(j))
Next
'set combocell values
comboCell.DisplayMember = "Name"
comboCell.ValueMember = "ID"
'set the default value to the current resolution index
Try
comboCell.Value = resolutions(currentResIndex)
Catch ex As Exception
End Try
comboCell.ValueType = GetType(cmbStruct)
comboCell.DataSource = resolutionList
editCameraTable("Resolution", i) = comboCell
Next
Change the EditMode property:
DataGridView1.EditMode = DataGridViewEditMode.EditOnEnter
There seems to be a nearly identical question and a very good answer. It involves using the click_event. Here is the link:
How to manually drop down a DataGridViewComboBoxColumn?
In the link:
Private Sub cell_Click(ByVal sender As System.Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
DataGridView1.BeginEdit(True)
If DataGridView1.Rows(e.RowIndex).Cells(ddl.Name).Selected = True Then
DirectCast(DataGridView1.EditingControl, DataGridViewComboBoxEditingControl).DroppedDown = True
End If
End Sub
I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer