function that runs when dynamically generated control is interacted with - vb.net

I've been Having trouble with making a sub that runs when my datagridview cell is doubleclicked. It is caused because the datagridview is programmatically created, rather than created by the designer. I have found a help website i will include that appears to be related to the issue.
Public Class seattemplatecreator
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Private WithEvents dgv_flightTemplate As DataGridView
'help from https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Public Sub init(ByVal dgv01 As DataGridView)
dgv_flightTemplate = dgv01
End Sub
Private Sub dgv_flightTemplate_CellMouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dgv_flightTemplate.CellMouseDoubleClick
MsgBox("workwd")
End Sub
Private Sub btn_createflight_Click(sender As Object, e As EventArgs) Handles btn_createflight.Click
'used https://social.msdn.microsoft.com/Forums/vstudio/en-US/e222f438-f060-4e61-ab28-523d02db91b2/how-to-programmatically-create-datagridview-with-empty-columns-and-rows?forum=vbgeneral
'to help with this part for automatically generating the datagridview
MsgBox(alphabet(0))
Dim dgv_flightTemplate As New DataGridView
Dim c As Integer = txb_columns.Text
Dim r As Integer = txb_rows.Text
For colcount As Integer = 0 To c - 1
Dim nc As New DataGridViewTextBoxColumn
nc.Name = "Seating Column"
dgv_flightTemplate.Columns.Add(nc)
Next
dgv_flightTemplate.Rows.Add(r)
For x = 0 To r - 1
dgv_flightTemplate.Rows(x).HeaderCell.Value = alphabet(x).ToString
Next
Me.Controls.Add(dgv_flightTemplate)
dgv_flightTemplate.Location = New Point(400, 400)
dgv_flightTemplate.AllowUserToAddRows = False
dgv_flightTemplate.AllowUserToDeleteRows = False
dgv_flightTemplate.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
dgv_flightTemplate.AutoResizeRows()
dgv_flightTemplate.AutoSize = True
End Sub
End Class
https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Edit: Olivier Jacot-Descombes response was perfect all that was needed was run the "Init" sub.
Public Class seattemplatecreator
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Private WithEvents dgv_flightTemplate As DataGridView
'help from https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Public Sub init(ByVal dgv01 As DataGridView)
dgv_flightTemplate = dgv01
End Sub
Private Sub dgv_flightTemplate_CellMouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dgv_flightTemplate.CellMouseDoubleClick
MsgBox("workwd")
End Sub
Private Sub btn_createflight_Click(sender As Object, e As EventArgs) Handles btn_createflight.Click
'used https://social.msdn.microsoft.com/Forums/vstudio/en-US/e222f438-f060-4e61-ab28-523d02db91b2/how-to-programmatically-create-datagridview-with-empty-columns-and-rows?forum=vbgeneral
'to help with this part for automatically generating the datagridview
MsgBox(alphabet(0))
Dim dgv_flightTemplate As New DataGridView
Dim c As Integer = txb_columns.Text
Dim r As Integer = txb_rows.Text
For colcount As Integer = 0 To c - 1
Dim nc As New DataGridViewTextBoxColumn
nc.Name = "Seating Column"
dgv_flightTemplate.Columns.Add(nc)
Next
dgv_flightTemplate.Rows.Add(r)
For x = 0 To r - 1
dgv_flightTemplate.Rows(x).HeaderCell.Value = alphabet(x).ToString
Next
Me.Controls.Add(dgv_flightTemplate)
dgv_flightTemplate.Location = New Point(400, 400)
dgv_flightTemplate.AllowUserToAddRows = False
dgv_flightTemplate.AllowUserToDeleteRows = False
dgv_flightTemplate.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
dgv_flightTemplate.AutoResizeRows()
dgv_flightTemplate.AutoSize = True
init(dgv_flightTemplate)
End Sub
End Class
Any help would be greatly appreciated
Thanks, Taine

You are not calling Init. But instead, you could as well directly assign to the field
dgv_flightTemplate = New DataGridView 'Note: No Dim here.
But even if you are creating the columns dynamically, you could add a grid with the designer. Just call
dgv_flightTemplate.Columns.Clear()
before adding columns.

Related

snap to grid MDI child forms vb.net

I'm developping a modular dashboard in Visual Basic that starts as an empty container than i can add modules to populate it.
The parent form is an MDI container and every module is a child MDI form that have fixed size.
I'd like to snap all of that child form to a grid both when the user creates a new one and when moves one of it inside the container (like they are magnetized to that grid).
How can i do that? Thanks
If I well understand you need something like this:
Private Class ImaginaryGrid
' You can change Columns and Rows as you want
Shared Rows As Integer = 3
Shared Cols As Integer = 3
Private Shared Function SnapToGrid(target As Form) As Point
Dim AllW As Integer = Screen.PrimaryScreen.WorkingArea.Width
Dim AllH As Integer = Screen.PrimaryScreen.WorkingArea.Height
Dim parent = target.MdiParent
If parent IsNot Nothing Then
AllW = target.MdiParent.ClientSize.Width
AllH = target.MdiParent.ClientSize.Height
End If
Dim currentPoint As Point = target.Location
Dim stepW As Integer = CInt(AllW / Cols)
Dim stepH As Integer = CInt(AllH / Rows)
Dim targetCol As Integer = CInt(currentPoint.X \ stepW)
Dim targetRow As Integer = CInt(currentPoint.Y \ stepH)
Dim newX As Integer = targetCol * stepW
Dim newY As Integer = targetRow * stepH
target.Location = New Point(newX, newY)
target.Width = stepW
target.Height = stepH
End Function
Shared Sub AttachFormToStayInGrid(frm As Form)
AddHandler frm.ResizeEnd, Sub()
SnapToGrid(frm)
End Sub
SnapToGrid(frm)
End Sub
End Class
Usage:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ImaginaryGrid.AttachFormToStayInGrid(Me)
End Sub
Take changes (if needed) as comments below shows:
Here's a beefed up version based on the same idea as G3nt_M3caj's suggestion:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ImaginaryGrid.Client = Me.Controls.OfType(Of MdiClient).FirstOrDefault
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frm As New Form
ImaginaryGrid.AttachFormToStayInGrid(frm)
End Sub
Private Class ImaginaryGrid
Public Shared WithEvents Client As MdiClient
Public Shared FixedChildSize As New Size(250, 150)
Private Shared Function SnapToGrid(target As Form) As Rectangle
Dim colX As Integer = target.Location.X / FixedChildSize.Width
Dim colY As Integer = target.Location.Y / FixedChildSize.Height
Dim newX As Integer = colX * FixedChildSize.Width
Dim newY As Integer = colY * FixedChildSize.Height
Return New Rectangle(New Point(newX, newY), FixedChildSize)
End Function
Shared Sub AttachFormToStayInGrid(frm As Form)
frm.Size = FixedChildSize
frm.FormBorderStyle = FormBorderStyle.FixedSingle
frm.MdiParent = Client.Parent
frm.Show()
SnapChild(frm)
AddHandler frm.ResizeEnd, Sub()
SnapChild(frm)
End Sub
AddHandler frm.LocationChanged, Sub()
If frm.WindowState = FormWindowState.Normal Then
snapRectangle = SnapToGrid(frm)
Client.Refresh()
End If
End Sub
End Sub
Private Shared Sub SnapChild(ByVal frm As Form)
If frm.WindowState = FormWindowState.Normal Then
Dim rc As Rectangle = SnapToGrid(frm)
frm.Bounds = rc
snapRectangle = Nothing
Client.Refresh()
End If
End Sub
Private Shared snapRectangle? As Rectangle
Private Shared Sub Client_Paint(sender As Object, e As PaintEventArgs) Handles Client.Paint
If snapRectangle.HasValue Then
e.Graphics.DrawRectangle(Pens.Black, snapRectangle)
End If
End Sub
End Class
End Class

Vb.net bindingsource.filter from a list of strings

i have in a windows.form a combobox and a datagridview,
i add rows in datagridview with a button and get the value(string) from combobox and if i double click on the row of datagridview i delete the row.
When i add the row i want to hide/disable/remove the combobox value and when i delete the row i want to restore it in combobox.
The combobox values are binding from dataset source and combobox is dropdownlist style.
I try some things until now but this is what i think is better approach and where i am:
Dim filterList As List(Of String) = New List(Of String)
Private Sub filterListAdd()
Dim dgResult As String
filterList .Clear() 'Clear the list so no duplicates
For i As Integer = 0 To combobox.Items.Count - 1
Dim a As String = combobox.GetItemText(combobox.Items(i))
For row As Integer = 0 To Dgview.RowCount - 1
For col As Integer = 0 To Dgview.ColumnCount - 1
Next
Surname = Dgview.Rows(row).Cells(0).Value.ToString
If dgResult = a Then
filterList .Add(a) 'Add to list
End If
Next
Next i
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button.Click
Dgview.Rows.Add(combobox.Text)
filterListAdd()
'Here i want to bindingsource.filter = filterList
End Sub
Private Sub Dgview_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles Dgview.MouseDoubleClick
Dgview.Rows.Remove(Dgview.CurrentRow)
'I Guess here with the same way i filter it again
End Sub
Any help will be appreciated, thanks in advance.
Panos
Public Class Form1
Dim clsItems As New ArrayList()
Private Sub RemoveComboItem()
Me.BindingSource.Position = Me.BindingSource.Find("1", Combobox.Text)
Dim 1Add As String = DirectCast(BindingSource.Current, DataRowView).Item("1").ToString
Dim 2Add As String = DirectCast(BindingSource.Current, DataRowView).Item("2").ToString
Dim 3Add As String = DirectCast(BindingSource.Current, DataRowView).Item("3").ToString
clsItems.Add(New MyItem(1Add, 2Add, 3Add))
BindingSource.RemoveCurrent()
End Sub
Private Sub AddComboItem(dg As DataGridView) ' Because i have two datagridviews
Dim 1 As String = dg.CurrentRow.Cells(0).Value.ToString()
For i = 0 To clsItems.Count - 1
If i <= clsItems.Count - 1 Then
If 1 = clsItems(i).1 Then
Dim drNewRow As DataRow
drNewRow = DeeDataSet.Tables("Table").NewRow()
drNewRow("1") = clsItems(i).1
drNewRow("2") = clsItems(i).2
drNewRow("3") = clsItems(i).3
DeeDataSet.Tables("Table").Rows.Add(drNewRow)
clsItems.Remove(clsItems(i)) ' Remove it from array so no duplicates
End If
End If
Next
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button.Click
RemoveComboItem()
End Sub
Private Sub Dgview_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles Dgview.MouseDoubleClick
AddComboItem(Dgview)
Dgview.Rows.Remove(Dgview.CurrentRow)
End Sub
End class
Public Class MyItem
Private m_s1 As String
Private m_s2 As String
Private m_s3 As String
Public Sub New(1As String, 2 As String, 3 As String)
M_sName = 1
M_sSurname = 2
M_sTitle = 3
End Sub
Public ReadOnly Property 1
Get
Return m_s1
End Get
End Property
Public ReadOnly Property 2
Get
Return M_s2
End Get
End Property
Public ReadOnly Property 3
Get
Return M_s3
End Get
End Property
End Class
In that form i don't update the dataset because every change i want to make it in other form, so when i finish from here the dataset.table has no changes.

Control Event (Changed) In DataTable

Helo:
How to overcome the problem of [RowChanged] event within the [DataTable] in the [DataGridView].
Explanation: You have created a column in the dataTable to find out which rows have been modified, in order to facilitate the knowledge of these rows to update them in the database, but the problem in the event(Row_Changed), can not be explained by more words in the code, see the column of (ISCHANGE) after modifying any row and cover the The Save button you find takes the value True and then False;
Public Class Class1
Public Table As DataTable
Sub New()
Table = New DataTable
Table.Columns.Add("IsChange", System.Type.GetType("System.Boolean"))
Table.Columns.Add("TeacherName", System.Type.GetType("System.String"))
Table.Columns("IsChange").DefaultValue = False
Dim dr As DataRow = Table.Rows.Add
dr("TeacherName") = "X1"
dr = Table.Rows.Add
dr("TeacherName") = "X2"
dr = Table.Rows.Add
dr("TeacherName") = "X3"
dr = Table.Rows.Add
AddHandler Table.RowChanged, New DataRowChangeEventHandler(AddressOf Row_Changed)
End Sub
Sub New(SourceDataTable As DataTable)
'Import DataTable
Table = SourceDataTable
End Sub
Public Sub Save()
GotoChange = False 'disable the event (Row_Changed)
For ALoop As Integer = 0 To Table.Rows.Count - 1
'=======================================
'Here Code Save To DataBase
'
'
'=======================================
Table(ALoop)("IsChange") = False 'RowChanged =False
Next
GotoChange = True 'Enabled the event (Row_Changed)
End Sub
Dim GotoChange As Boolean = True 'This variable is to disable the event (Row_Changed)
Private Sub Row_Changed(ByVal sender As Object, ByVal e As DataRowChangeEventArgs)
If Not GotoChange Then Exit Sub
If e.Action = DataRowAction.Add Or e.Action = DataRowAction.Change Then
If CBool(e.Row("IsChange")) = False Then
MsgBox("IsChange")
e.Row("IsChange") = True 'If [True] this means that the row has been changed
End If
End If
End Sub
End Class
Form Code :
Change Any Row Then Button Save:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim A As New Class1
Me.DataGridView1.DataSource = A.Table
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim A As New Class1(Me.DataGridView1.DataSource)
'Change Value Any Row Then Button Save
'Here Problem: Show Column(IsChang) After Save
'The value First (False) Then (True)
A.save()
End Sub
End Class

Datagridview doesnt auto select first row after filling datasource

i have datagridview with 4 columns
[Nam] , [ID] , [Shuru] , [Payan]
second column ([ID]) is hidden and is used to gather some details about the data.
this is the Load code :
Private Sub SalMali_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DGV_SalMaliTableAdapter.Fill(Me.FDBDataSet.DGV_SalMali)
End Sub
which retrieves everything in DGV_SalMali table.
i know that datagridview automatically selects first row after a fill so i put a function in the Selection Change to retrieve data. here is the code :
Private Sub DGV_SalMaliDataGridView_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DGV_SalMaliDataGridView.SelectionChanged
refreshDT()
End Sub
Public Sub refreshDT()
Dim cnt As Integer = DGV_SalMaliDataGridView.Rows.Count
If cnt = 0 Then
GoTo line
End If
unlockAll()
Dim sel As String = DGV_SalMaliDataGridView.SelectedRows(0).Cells(1).Value
Dim dt As New DataTable
dt = SalMaliTA.GetData_SalMali_B_ID(sel)
Dim dtr As DataRow = dt.Rows(0)
TextBox1.Text = dtr.Item(4)
MaskedTextBox1.Text = mc.MtoS(dtr.Item(1))
MaskedTextBox2.Text = mc.MtoS(dtr.Item(2))
CheckBox1.Checked = dtr.Item(3)
Exit Sub
line:
lockAll()
End Sub
but when I call refreshDT() the selection doesn't work anymore. it throws an error on line 8 of refreshDT()
sub { exactly here : Dim sel As String = DGV_SalMaliDataGridView.SelectedRows(0).Cells(1).Value }
Thrown: "Index was out of range. Must be non-negative and less than
the size of the collection."
(System.ArgumentOutOfRangeException) Exception Message = "Index was
out of range. Must be non-negative and less than the size of the
collection.", Exception Type = "System.ArgumentOutOfRangeException"
datagridview has rows and i dont know what the problem is.
thanks for help.
you're currently checking if there are any rows but not any selected rows:
Public Sub refreshDT()
Dim cnt As Integer = DGV_SalMaliDataGridView.Rows.Count
If cnt = 0 Then
lockAll()
Exit Sub
End If
If DGV_SalMaliDataGridView.SelectedRows.Count = 0 Then
DGV_SalMaliDataGridView.Rows(0).Selected = true
End If
unlockAll()
Dim sel As String = DGV_SalMaliDataGridView.SelectedRows(0).Cells(1).Value
Dim dt As New DataTable
dt = SalMaliTA.GetData_SalMali_B_ID(sel)
Dim dtr As DataRow = dt.Rows(0)
TextBox1.Text = dtr.Item(4)
MaskedTextBox1.Text = mc.MtoS(dtr.Item(1))
MaskedTextBox2.Text = mc.MtoS(dtr.Item(2))
CheckBox1.Checked = dtr.Item(3)
End Sub

looping through datagridview

Mine is a windows app. containing forms named BOM nd BOMSelected..
There is datagridview in BOM which contains checkbox column.. When the user selects checkbox, the selected rows should be seen in the datagridview of other form, SelectedBom..
I have coded but don't get it working.. Some error..
Can you please help ??
Your Help is greatly appreciated..
Here is what i have done !!
Public Class SelectedBom
Private Sub SelectedBom_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'HemDatabase1DataSet4.partno' table. You can move, or remove it, as needed.
'Me.PartnoTableAdapter.Fill(Me.HemDatabase1DataSet4.partno)
Dim count As Integer = 0
For j As Integer = 0 To BOM.dgv1.RowCount - 1
If BOM.dgv1.Rows(j).Cells(0).Value = True Then
Dim ro As New DataGridViewRow
DataGridView2.Rows.Add(ro)
For i As Integer = 0 To BOM.dgv1.ColumnCount - 1
Me.DataGridView2.Rows(count).Cells(i).Value = BOM.dgv1.Rows(j).Cells(i).Value
Next
count += 1
End If
Next
End Sub
End Class
Try,
For Each row As DataGridViewRow In BOM.dgv1.Rows
Dim obj(row.Cells.Count - 1) As Object
For i = 0 To row.Cells.Count - 1
obj(i) = row.Cells(i).Value
Next
Me.DataGridView2.Rows.Add(obj)
Next
EDIT:
Demo:
Add Button1 and DataGridView1 in BOM form
Public Class BOM
Public Class Sample
Public Property Satus As Boolean
Public Property Name As String
Public Property ID As Integer
End Class
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
SelectedBom.Show()
End Sub
Private Sub BOM_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim myList As New List(Of Sample)
myList.Add(New Sample() With {.ID = 1, .Name = "A"})
myList.Add(New Sample() With {.ID = 2, .Name = "B"})
myList.Add(New Sample() With {.ID = 3, .Name = "C"})
DataGridView1.DataSource = myList
End Sub
End Class
Add DataGridView1 in SelectBOM form
Public Class SelectedBom
Private Sub SelectedBom_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim i As Integer = 0
DataGridView1.AutoGenerateColumns = False
DataGridView1.Columns.Add("Name", "Name")
DataGridView1.Columns.Add("No", "No")
For Each row As DataGridViewRow In BOM.DataGridView1.Rows
If DirectCast(row.Cells(0).Value, Boolean) Then
DataGridView1.Rows.Add(row.Cells(1).Value, row.Cells(2).Value)
End If
Next
End Sub
End Class
Maybe instead of using the for each statement, you should instead use:
for istep as integer = 0 to datagridview.rowcount - 2
With the for each syntax, you can't assign a value to the individual row as you walk down the row.