VB.net: Can't run a public sub in another form - vb.net

I have a Main (MDIParent) and Ticket (MDIChild). In Ticket form, there is a listview that displays the previous ticket trouble, pending and open ticket. When I add a new ticket trouble, there is a button BtnCreat_T, it will appear the TicketAdd form. The Ticket form will not close and I use the showdialog() for TicketAdd to show. When I add the new ticket trouble in TicketAdd form, the listview in Ticket form will not refresh, update, or reload.
Also, I noticed that in TicketAdd form I can't run the Public Sub ViewRecords created in Ticket form.
So here is my code in Ticket form Public Sub ViewRecords. I call this in Ticket form load:
Public Sub ViewRecords()
Dim i As Integer = 0
LvTicket.Items.Clear()
con.Open()
SQLString = String.Empty
SQLString = "SELECT * FROM TblTickets ORDER BY Ticket_ID DESC"
SQLDA = New SqlDataAdapter(SQLString, con)
Using SQLDT As New DataTable
SQLDA.Fill(SQLDT)
Do Until i = SQLDT.Rows.Count
With LvTicket
.Items.Add(SQLDT.Rows(i)("Ticket_ID"))
With .Items(.Items.Count - 1).SubItems
.Add(SQLDT.Rows(i)("Dept"))
.Add(SQLDT.Rows(i)("Aff_Per"))
.Add(SQLDT.Rows(i)("N_Prob"))
.Add(SQLDT.Rows(i)("Prob_Des"))
.Add(SQLDT.Rows(i)("DateTime"))
.Add(SQLDT.Rows(i)("Findings"))
.Add(SQLDT.Rows(i)("Status"))
End With
i += 1
End With
Loop
End Using
con.Close()
End Sub
And this is my code for adding the new trouble ticket in TicketAdd form BtnCreat_T button:
Private Sub BtnCreateT_Click(sender As Object, e As EventArgs) Handles BtnCreateT.Click
If CmbDept.Text = "" Or TxtAffectedP.Text = "" Or CmbNOProblem.Text = "" Or TxtProbD.Text = "" Or TxtFindings.Text = "" Or CmbStatus.Text = "" Then
MsgBox("Their is an empty field, please check!", MsgBoxStyle.Exclamation, "Ticket Details")
Else
If MsgBox("Are all fields are correct? Please double check!", MsgBoxStyle.Information + MsgBoxStyle.YesNo, "Ticket Details") = MsgBoxResult.Yes Then
GetTicket()
con.Open()
SQLString = String.Empty
SQLString = "INSERT INTO TblTickets (Ticket_ID, Dept, Aff_Per, N_Prob, Prob_Des, DateTime, Findings, Status)" &
"VALUES (#TID, #D, #AP, #NP, #PD, #DT, #F, #S)"
SQLCmd = New SqlCommand(SQLString, con)
SQLCmd.Parameters.AddWithValue("#TID", LblTicketID.Text)
SQLCmd.Parameters.AddWithValue("#D", CmbDept.Text)
SQLCmd.Parameters.AddWithValue("#AP", TxtAffectedP.Text)
SQLCmd.Parameters.AddWithValue("#NP", CmbNOProblem.Text)
SQLCmd.Parameters.AddWithValue("#PD", TxtProbD.Text)
SQLCmd.Parameters.AddWithValue("#DT", DTPicker.Value)
SQLCmd.Parameters.AddWithValue("#F", TxtFindings.Text)
SQLCmd.Parameters.AddWithValue("#S", CmbStatus.Text)
SQLCmd.ExecuteNonQuery()
MsgBox("Data has been saved! Your Ticket Number is: " & LblTicketID.Text, MsgBoxStyle.OkOnly, "Ticket Details")
con.Close()
EmptyField()
CmbDept.Select()
Ticket.ViewRecords()
Else
CmbDept.Select()
End If
End If
End Sub
After I click the BtnCreat_T button, the TicketAdd form will not close and the listview in Ticket form must be updated or refresh.
There is no error when running this code but I can't reload or update the listview in Ticket form.

As you mentioned you show the TicketAdd Form modal (.ShowDialog())
So I would suggest as long this TicketAdd from is showing, it's not realy relevant to update the Ticket form, because your application focus is clampt on your ticketAdd-Dialog.
After you close your TicketAdd form you can call ViewRecords from within the sub where you showed your TicketAdd form. There you have direct access to your true Instance of Ticketform (mentioned by #JayV)
But if you realy have to update every record as it gets saved you can handle it with an action you pass to your TicketAdd form
In your Ticketform where you show your TicketAdd, set the Action (Reference to the Sub Signature of Ticketform)
Dim lTicketAdd As New TicketAdd
lTicketAdd.SetUpdateData(AddressOf ViewRecords)
lTicketAdd.ShowDialog()
Extend your TicketAdd form with a Sub to asign the Action-Reference and where you save your DataRecord call this Action
'And Action to hold the Reference to your ViewRecords Code from the parent Form
Private _RefreshData As Action
'A sub to set this Action Reference
Public Sub SetUpdateData(ByVal vDelegation As Action)
_RefreshData = vDelegation
End Sub
Private Sub BtnCreateT_Click(sender As Object, e As EventArgs) Handles BtnCreateT.Click
.....
'Your code from above
'Instead of calling ViewRecord, call the Action
If _RefreshData IsNot Nothing Then
_RefreshData.Invoke()
End If
End Sub

Related

How to refresh a datagrid on a parent form, from a child form

on frmBrands there a dgBrands that gets it's data in subLoadDgBrands. on frmBrand you can add a record to the dtBrands when you fire the btnSave_Click eventhandler. that same event handler also calls frmBrands.subLoadDgBrands however it does not refresh the dg that is displayed. I need it to refresh the dg on frmBrands when you finish the save procedure on frmBrand, as i only want to refresh if the save was succesfull, and for a different form i need to pass back an integer to that sub
Here's the relevant code
```VB
Public Class frmBrands
Friend Sub subLoadDgBrands()
dtBrands = fnGetBrand(0) 'Go get the data for the DataGridView
dgBrands.DataBindings.Clear()
dgBrands.DataSource = Nothing
dgBrands.Rows.Clear()
dgBrands.Columns.Clear()
If dtBrands IsNot Nothing Then
dgBrands.DataSource = dtBrands
dgBrands.Refresh()
subFormatDgBrands()
End If
End Sub
End Class
```
This event handler needs to refresh the datagrid on the instance of frmBrands that this form was opened through
```VB
Public Class frmBrand
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
'intID is passed by parent form = intBrand_ID
'intSupplier_ID is declared at the top of the form and set correctly by event handler
Dim intResult As Integer = 0
Dim strMessage As String = ""
Dim strBrandName As String = txtBrand.Text
'string builder that checks if the important fields are filled in
If strBrandName = "" Then 'if there is nothing written in str
If strMessage = "" Then 'and if the error message is empty
strMessage = "Please provide a brand name" 'then add the error message to the string
Else 'if the error message isn't empty '
strMessage &= "and brand name" 'then add str to the message
End If
End If
If intSupplier_ID < 1 Then 'if there is a 0 or negative ID selected, can also use cboSupplier.selectedValue
If strMessage = "" Then 'and if the error message is empty
strMessage = "Please provide a supplier" 'then add the error message to the string
Else 'if the error message isn't empty
strMessage &= "and supplier" 'then add "Title" to the message
End If
End If
'save string checker
If strMessage <> "" Then 'if there is something in the message
MsgBox(strMessage) 'display it
Else 'if there's nothing in the message
intResult = fnSaveBrand(intID,
intSupplier_ID,
strBrandName) 'We can save
'Additional logic loop that gives some feedback if it isn't saved
If intResult < 1 Then 'feedback number if the save wasn't succesfull
MsgBox("ID fault") 'Will let the user know it didn't save
Else 'the save was succesfull
**frmBrands.subLoadDgBrands()** 'Needs to refresh the datagrid on the instance of frmBrand**s** that this form was opened through
Me.Close() 'then it closes the form
End If
End If
End Sub
End Class
```
If you want to reflect the changes even frmBrand is still open, make subLoadDgBrands as Public then after your insert query was executed, add this
Dim _frmBrands As frmBrands = TryCast(Me.Owner, frmBrands)
_frmBrands.subLoadDgBrands()
If you want to reflect the changes right after the frmBrand was close, then replace Me.Close with Me.DialogResult = Windows.Forms.DialogResult.OK. Then in your code for opening frmBrand use
Using frmBrand As New frmBrand()
frmBrand.ShowDialog(Me)
If frmBrand.DialogResult = Windows.Forms.DialogResult.OK Then
subLoadDgBrands()
End If
End Using

VB.NET ContextMenuStrip dynamic subitems. How to add event on each subitems?

how can I add an event or get the text of the subitem of the contextmenustrip control after I clicked the subitem?
Here's my code:
Try
enrollment_conn.Open()
command = New SqlCommand("SELECT DISTINCT Section FROM dbo.Enrollees WHERE Grade = '" & Main.Enrollees_Cbx_grade.Text & "' AND Strand = '" & Main.Enrollees_Cbx_strand.Text & "' AND School_Year = '" & Main.Enrollees_Cbx_sy.Text & "' AND Enrolled = 'Yes'", enrollment_conn)
reader = command.ExecuteReader
Main.Enrollees_CMS_enrolleesList.Items.Clear()
Dim tm = New ToolStripMenuItem("Filter")
Main.Enrollees_CMS_enrolleesList.Items.Add(tm)
While reader.Read
tm.DropDownItems.Add(reader.Item("Section").ToString)
End While
enrollment_conn.Close()
Catch ex As Exception
MsgBox(ex.Message, vbExclamation)
End Try
The code above adds a Toolstripitem called Filter and when I right click my datagridview. The item Filter shows and has subitems which I added by using a query. The question is how can I get the text or add an event to the subitems? Thanks.
The Add method that you're using here is overloaded:
tm.DropDownItems.Add(reader.Item("Section").ToString)
You should use the overload that lets you specify a Click event handler:
tm.DropDownItems.Add(reader.Item("Section").ToString, Nothing, AddressOf MenuItem_Click)
The third argument is a delegate to the event handler method. If you're not comfortable writing that from scratch yourself, the simplest option is to let the IDE create one for you. Simply double-click a menu item in the designer and an event handler will be generated in the usual way. You can then delete the Handles clause from the end of the declaration and change the name to something more generic. You can then access the menu item that was clicked via the sender parameter, which is always a reference to the object that raised the event:
Private Sub MenuItem_Click(sender As Object, e As EventArgs)
Dim menuItem = DirectCast(sender, ToolStripMenuItem)
'Use menuItem here.
End Sub
If you need data for each menu item then you can assign it to the Tag property when you create it, e.g.
tm.DropDownItems.Add(reader.Item("Section").ToString,
Nothing,
AddressOf MenuItem_Click).Tag = reader.Item("Data")
and then get it back again in the event handler:
Private Sub MenuItem_Click(sender As Object, e As EventArgs)
Dim menuItem = DirectCast(sender, ToolStripMenuItem)
Dim data = menuItem.Tag
'Use data here.
End Sub

Add data into new added row in `DataGridView` from `DataBindingSource`

In Form4 i have a DataGridView named DbTableDataGridView.
In Form3 there is a set of fields (text boxes) that are all bound to the DbTableBindingSource . When I run application the Form4 shows up. There is a button to open new form (Form3) and in there enter details about customers to be added as new row into database (DataGridView). My code for the "Add" button in Form4 looks like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.DbTableDataGridView.Refresh()
Me.DbTableBindingSource.AddNew()
Form3.ShowDialog()
Form3.ImiéTextBox.Text = ""
Form3.NazwiskoTextBox.Text = ""
Form3.Numer_TelefonuTextBox.Text = ""
Form3.Numer_RejestracyjnyTextBox.Text = ""
Form3.MarkaTextBox.Text = ""
Form3.ModelTextBox.Text = ""
Form3.Poj_SilnikaTextBox.Text = ""
Form3.RocznikTextBox.Text = ""
Form3.PaliwoTextBox.Text = ""
Form3.Data_PrzyjeciaDateTimePicker.Value = DateTime.Now
Form3.RichTextBox1.Text = ""
End Sub
It does add new row, selects it and clears entries in the text boxes (that are bound into 'DbTableBindingSource'.
In this form after I fill in all the fields I press button save:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Me.Validate()
Form4.DbTableBindingSource.EndEdit()
Me.DbTableTableAdapter.Update(CartronicDBDataSet.dbTable)
TableAdapterManager.UpdateAll(CartronicDBDataSet)
DbTableTableAdapter.Fill(Form4.CartronicDBDataSet.dbTable)
MsgBox("Saved")
Catch ex As Exception
MessageBox.Show("Blad zapisu. Sprobuj ponownie. W razie potrzeby zamknij, a nastepnie uruchom ponownie program Cartronic")
End Try
End Sub
It goes to the message "Saved" but actually does not fill in added new recently.
Any thoughts?
There is no link that I can see between Form3 and your data.
I'd recommend passing the newly created data row to a new instance of Form3.
Get the reference to your newly added row
Create a new Form3 (avoid default instance forms, they're ugly and evil). This will mean you don't need to clear the textboxes as you have a brand new form every time.
Pass the datarow into your form where you will bind it directly to the textboxes
Dim newRow = CType(Me.DbTableBindingSource.AddNew(), DataRow)
Using frmEditor As New Form3
frmEditor.DataSource = newRow
frmEditor.ShowDialog()
End Using
In form3 add the property (or preferably a constructor)
Private mDataSource As DataRow
Public Property DataSource As DataRow
Get
Return mDataSource
End Get
Set(value As DataRow)
mDataSource = value
Me.ImiéTextBox.DataBindings.Add("Text", mDataSource, "ImiéFieldName")
' ....
End Set
End Property
If you use this approach then you can get rid of all of the textbox clearing code.
I have done what you have suggested but little bit simpler.
Assigned all text boxes to each cell in current row as follows:
Form4.DbTableDataGridView.CurrentRow.Cells(5).Value = Me.NazwiskoTextBox.Text.ToString
Form4.DbTableDataGridView.CurrentRow.Cells(4).Value = Me.ImiéTextBox.Text.ToString
It works fine.
Cheers

UltraWinGrid Auto Refresh

In my vb.net project, I have 3 forms. home_mdi, Viewfrm and AddDatafrm.
Viewfrm has an UltraWinGrid on it, which is displaying some data. When I click the add data button, AddDatafrm opens. When data is saved, the form then closes.
At this point, I want the UltraWinGrid on Viewfrm to update/refresh and display the data that I added. At the moment, it doesn't display it until I close Viewfrm and then open it again.
The images show this. (Data is not there at the start, it then gets added and does not appear. The final image is the form displaying the new data, after I've re-opened it.
How do I change this?
Current code:
To open the Add form
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Using fp = New frmAddData(Globals.m_database)
If fp.ShowDialog() = DialogResult.OK Then
ugData.DataSource = Nothing
getPeople()
End If
End Using
End Sub
To save the entered information (on the Add form)
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim m_cn As New OleDbConnection
m_cn = Globals.m_database.getConnection()
If txtFirstName.Text = "" Then
MsgBox("First name cannot be blank")
ElseIf txtLastName.Text = "" Then
MsgBox("Last name cannot be blank")
ElseIf txtAge.Text = "" Then
MsgBox("Age cannot be blank")
ElseIf txtPostCode.Text = "" Then
MsgBox("Postcode cannot be blank")
Else
Dim personID As Integer = database.SaveNewPerson(txtFirstName.Text, txtLastName.Text, txtAge.Text, txtPostCode.Text, m_cn)
MsgBox("Save successful")
txtFirstName.Text = ""
txtLastName.Text = ""
txtAge.Text = ""
txtPostCode.Text = ""
Globals.savedValue = True
Me.Close()
End If
End Sub
Call to load the database on the View form:
Public Sub getPeople()
Try
Dim sql As String = "SELECT * FROM tblPerson ORDER BY [personID] ASC;"
Dim cm As New OleDbCommand(sql, Globals.m_database.getConnection())
Dim da As New OleDbDataAdapter(cm)
Dim dt As New DataTable()
da.Fill(dt)
ugData.DataSource = dt
Catch Ex As Exception
mdi1.errorLog(Ex.Message, Ex.StackTrace)
MsgBox("Failed to retrieve data, refer to error log")
End Try
End Sub
In a WinForm app, a modal dialog is closed automatically by the engine if a button is pressed and its DialogResult property is set to anything but None. Then the Winform engine sets the form DialogResult to the same property of the button, exits from the ShowDialog call and returns the DialogResult property of the button clicked.
Usually this is more than enough to handle situations like yours above. (Or, in general situations where a user choose between Yes/No or OK/Cancel scenarios)
In your code (as explained in chat) you have the DialogResult property of the Save button set to DialogResult.None. This, means that the Winforms engine doesn't close automatically your form and you need to write your own closing routine.
But, if you forget to set the Form property DialogResult to DialogResult.OK, your calling code will never be able to refresh the grid because the test for DialogResult.OK fails.
So, whatever closing code you have to close the fromAddData instance, remember to set the form DialogResult property with
Me.DialogResult = DialogResult.OK
or, if something is gone wrong, with
Me.DialogResult = DialogResult.Cancel

Send value to parent then close child form, on event

I have a parent form with a combobox populated from a database, from which the user can select. The last value in the combo box is "add new", if the user selects this, a child form opens for the user to add a new value to the database. I have a button press event to add this value to the database, send the new return value to the parent and close the form. The parent should then select the new value from it's combo box and wait for the user to perform another action.
However, the code to send the return value to parent and close the form isn't working correctly. I hide the child, then call a function on it with the parent to access the return value. At this point the child form shows and the code stops before it runs another hide or close.
How can I fix this (code below)?
Parent Combobox event:
Private Sub cmbLocations_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbLocations.SelectedIndexChanged
If Not cmbLocations.SelectedIndex = -1 Then
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
If diaAddLocation.IsAccessible = False Then diaAddLocation.Activate()
diaAddLocation.RequestSender = Me
diaAddLocation.ShowDialog()
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaAddLocation.formresult)
diaAddLocation.Close()
diaAddLocation.Dispose()
Else
bttYes.Enabled = True
End If
End If
End Sub
Child Button Press and Return value function
Public Sub bttAddLOCtoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bttAddLOCtoDatabase.Click
Dim LocationToBeAdded As String
LocationToBeAdded = "'" & TextBox1.Text & "'"
AddLocation("'" & textbox1.Text & "'")
FormResult = textbox1.Text
GetLocations()
frmFieldMaster.InitialiseNewParameter()
Me.Hide()
End Sub
Public Function Result() As String
Return FormResult
End Function
EDIT:
code with Steve's solution implemented:
Public Sub bttAddLOCtoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bttAddLOCtoDatabase.Click
Dim LocationToBeAdded As String
LocationToBeAdded = "'" & TextBox1.Text & "'"
AddLocation("'" & textbox1.Text & "'")
FormResult = textbox1.Text
GetLocations()
frmFieldMaster.InitialiseNewParameter()
DialogResult = Windows.Forms.DialogResult.OK
'me.Hide()
End Sub
Public Function Result() As String
Return FormResult
Me.Close()
End Function
Private Sub cmbLocations_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbLocations.SelectedIndexChanged
Dim ValueTaken As Boolean = False
If Not cmbLocations.SelectedIndex = -1 Then
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
Using diaaddlocation = New diaAddLocation
diaaddlocation.requestsender = Me
If DialogResult.OK = diaaddlocation.showdialog Then
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaaddlocation.result)
diaaddlocation.close()
ElseIf DialogResult.Cancel = diaaddlocation.showdialog Then
cmbLocations.SelectedIndex = -1
End If
End Using
Else
bttYes.Enabled = True
End If
End If
End Sub
When I run the code it enters IF DialogResult.OK... and opens the child. Then when I close the child the parent runs the next two lines of code and get the result from the child. After this the parent runs the line IF DialogResult.OK... again and stops with the child open. The code never reaches the diaaddlocation.close line.
You don't need all of this. You could try something like this
If cmbLocations.SelectedIndex = cmbLocations.Items.Count - 1 Then
Using diaAddLocation = new diaAddLocation()
diaAddLocation.RequestSender = Me
if DialogResult.OK = diaAddLocation.ShowDialog() then
FillLocations()
cmbLocations.SelectedIndex = LocationFromLocationName(diaAddLocation.formresult)
End If
End Using
Else
.....
This requires the DialogResult property for bttAddLOCtoDatabase set to DialogResult.OK and the child form AcceptButton property set to bttAddLOCtoDatabase. Now you could remove the Hide() call inside the bttAddLOCtoDatabase_Click method
This works because, until you don't exit the Using statement, your child form is still available to read its properties (results)
EDIT: Not related to the main problem, but these lines are wrong:
ElseIf DialogResult.Cancel = diaaddlocation.showdialog Then
cmbLocations.SelectedIndex = -1
you should go with
Using diaAddLocation = new diaAddLocation()
diaAddLocation.RequestSender = Me
Dim dr = diaAddLocation.ShowDialog()
if dr = DialogResult.OK then
....
else if dr = DialogResult.Cancel then
....
end if
I don’t understand what is issue but if you are not getting value of “FormResult”
It doesn’t matter if you close from but it will be better to set DialogResult before closing it, cause you are showing it as dialog (showdialog)
Verify that diaAddLocation is instance of you window not the window class directly
If name of you form is frmdiaAddLocation then do not use it like
frmdiaAddLocation.showdialog
use it like
Dim diaAddLocation AS frmdiaAddLocation = New frmdiaAddLocation()
diaAddLocation.ShowDialog()
only using like this way will provide you result value