Send value to parent then close child form, on event - vb.net

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

Related

Textbox not refreshing

Dim VoucherOpenConnection As New OleDbConnection
' VoucherOpenConnection = New OleDbConnection
VoucherOpenConnection.ConnectionString = "My Connection String"
Dim VoucherString As String = "My Query"
Dim DAVoucherString As New OleDbDataAdapter(VoucherString, VoucherOpenConnection)
Dim DTVoucherString As New DataTable
DAVoucherString.Fill(DTVoucherString)
If DTVoucherString.Rows.Count <> 0 Then
cmbCategory.Text = DTVoucherString.Rows(0).Item(8).ToString
txtDetails.Text = DTVoucherString.Rows(0).Item(2).ToString
txtshop.Text = DTVoucherString.Rows(0).Item(3).ToString
txtAmount.Text = DTVoucherString.Rows(0).Item(4).ToString
txtRemarks.Text = DTVoucherString.Rows(0).Item(5).ToString
txtInvoiceNum.Text = DTVoucherString.Rows(0).Item(11).ToString
txtCashAmt.Text = DTVoucherString.Rows(0).Item(6).ToString
Me.Refresh()
Else
MsgBox("No valid record could be found(Cash)!!")
End If
I have the above code inside a sub procedure and call it from another form. When the sub is called the first time, all the textboxes display the correct values. But when I try again, the values do not update. Putting a breakpoint in the sub reveals that the code is working correctly as hovering the mouse over the textboxes shows the correct values.
I have already tried the following methods to no avail:
Me.Refresh
Me.Update
Textbox.update/refresh
This is in VB.NET 2019.
Edit:Code in the calling form:
Private Sub DGVTotalReport_CellMouseDoubleClick(sender As Object, e As
DataGridViewCellMouseEventArgs) Handles
DGVTotalReport.CellMouseDoubleClick
Dim ExpForm As New ExpenseEntry
My.Settings.TranCodeExpOpen =
DGVTotalReport.Rows(e.RowIndex).Cells(8).Value
If My.Settings.ExpenseForm = False Then
ExpForm.Show()
ExpForm.OpenVoucher()
My.Settings.ExpenseForm = True
Else
My.Settings.ExpenseForm = True
ExpForm.Activate()
ExpForm.OpenVoucher()
ExpForm.Refresh()
End If
End Sub

Have to Click Form To Give Focus

I have a main form with buttons that open a custom message box form. It works fine if it's just a message and the user just needs to click OK. But if the answer to that message box is important, like "Are you sure you want to delete this file?" I use a while loop to wait for the user to respond and once they do then a flag is set from false to true and the response is recorded.
For some reason any response that uses a while loop to wait is causing the message box form to not have focus after being called. Requiring the user to first click on the form, and then click on OK.
So far I've tried using form.Activate() instead of form.Show(), as well as calling Application.DoEvents() inside the while loop since I believed the while loop was taking focus away from the message form immediately after being called. Neither solved the issue.
Code from a message box that works as intended:
If cmbLoadProgram.SelectedItem = "" Then
frmMessageBox.lblHeader.Text = "Set-Up"
frmMessageBox.lblMessageText.Text = "No Program Selected!"
frmMessageBox.Show()
Exit Sub
End If
Code from a message box that needs to be clicked twice:
If btnGetHexStart.Visible = False And cmbStartCondition.SelectedItem = "Pixel" Then
frmMessageBox.lblHeader.Text = "Hex Set-Up"
frmMessageBox.lblMessageText.Text = "Reset Hex Code Data?"
frmMessageBox.Show()
Me.Hide()
While Flag = False
If frmMain.OKCancel = "OK" Then
btnGetHexStart.Visible = True
btnGetHexStart.Enabled = True
btnGetHexStart.PerformClick()
Flag = True
End If
frmMain.delay(20)
End While
End If
I'm wanting both options to only need to be clicked once in order to confirm or cancel the action. Instead of the while loop questions needing to be clicked twice.
This just an idea from me, just how to open msgboxform, here we need MessageForm and one module1, for example:
Public Class MessageForm
'You can assign any variable to show any data in messageform display
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
theResult = MsgBoxResult.Ok
Me.Close()
Me.Dispose()
End Sub
Private Sub bttcancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bttcancel.Click
theResult = MsgBoxResult.Cancel
Me.Close()
Me.Dispose()
End Sub
End Class
Module Module1
Public theResult As MsgBoxResult
'You can add some parameter here to submit to MessageForm
Public Function myMessageBox() As MsgBoxResult
myMessageBox = MsgBoxResult.Cancel
MessageForm.ShowDialog()
myMessageBox = theResult
End Function
End Module
and then you can call the myMessageBox anywhere like this:
'if myMessageBox procedure have parameter, apply the paramters too
dim myRslt = myMessageBox()
You don't need to create a form,You can use DialogResult and MessageBox.Show, code:
Dim Result As DialogResult = MessageBox.Show("Set-Up" & vbCrLf & "No Program Selected!", "Warning", MessageBoxButtons.OKCancel)
If Result = DialogResult.OK Then
ElseIf Result = DialogResult.Cancel Then
End If

vb.net combobox to return value of another column

I have two comboboxes. The second one is dependant on the first. I then pass the selected values to a second form as objects. My code works perfectly up to here. But I also need to pass a third object to the second form (i.e. plaasnopass) based on the selection of the second combobox (i.e cmbPlaasnaam). This value however is in another column. My code below runs without errors , but the third value is not passed to the second form.
Public Class ParskaartjieKiesFrm
Dim obj As New Parskaartjies
Private Sub ParskaartjieKiesFrm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'SkeduleringDatabasisDataSet.wingrd13' table. You can move, or remove it, as needed.
Me.Wingrd13TableAdapter.Fill(Me.SkeduleringDatabasisDataSet.wingrd13)
With CmbAliasnaam
.BeginUpdate()
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.ListItems
Dim qry = From zc As SkeduleringDatabasisDataSet.wingrd13Row In SkeduleringDatabasisDataSet.wingrd13 _
Select zc.Aliasnaam Distinct Order By Aliasnaam
For Each ALIASNAAM As String In qry
.Items.Add(ALIASNAAM)
Next
.EndUpdate()
End With
With CmbPlaasnaam
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.ListItems
.Enabled = False
End With
End Sub
Private Sub CmbAliasnaam_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CmbAliasnaam.SelectedIndexChanged
obj.aliasnaampass = CmbAliasnaam.SelectedItem
With CmbPlaasnaam
.SelectedIndex = -1
.Items.Clear()
.Enabled = False
End With
If CmbAliasnaam.SelectedIndex > -1 Then
CmbPlaasnaam.BeginUpdate()
Dim Aliasnaam As String = CmbAliasnaam.Items(CmbAliasnaam.SelectedIndex).ToString
Dim qry = From zc As SkeduleringDatabasisDataSet.wingrd13Row In SkeduleringDatabasisDataSet.wingrd13 _
Where zc.Aliasnaam = ALIASNAAM Select zc.Plaasnaam Distinct _
Order By Plaasnaam
For Each plaasnaam As String In qry
CmbPlaasnaam.Items.Add(plaasnaam)
Next
If CmbPlaasnaam.Items.Count > 0 Then
CmbPlaasnaam.Enabled = True
End If
CmbPlaasnaam.EndUpdate()
End If
End Sub
Private Sub CmbPlaasnaam_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CmbPlaasnaam.SelectedIndexChanged
obj.plaasnaampass = CmbPlaasnaam.SelectedItem
obj.plaasnopass = CmbAliasnaam.SelectedValue
obj.Show()
Me.Close()
End Sub
End Class
How do I go about ?
Regards
According to your comment, I understood that you have combo box loaded from
select a from t
but this gives you single value, and you want to load
select a, b from t
and pass both values to next form.
It is helpful that you're using LINQ!! Modify it. But first declare new type
Public Class CboItem
Public Property Display As String
Public Property Value As String ' <-- any datatype
' .... any number of properties here
End Class
Dim qry =
(From zc As SkeduleringDatabasisDataSet.wingrd13Row
In SkeduleringDatabasisDataSet.wingrd13 _
Where zc.Aliasnaam = ALIASNAAM
Select New CboItem() With { .Display = zc.Plaasnaam, .Value = zs.[...] }).
Distinct(function(item)...).OrderBy(function(item)...)
CmbAliasnaam.DisplayMember = "Display"
CmbAliasnaam.ValueMember = "Value"
CmbAliasnaam.DataSource = qry.ToList()
Now you can pass to your form selected item or whatever you get out of it. for example
Dim item As CboItem = TryCast(CmbAliasnaam.SelectedItem, CboItem)
If item IsNot Nothing Then
frm.SetSelected(item.Display, item.Value, item.anyOtherProperty)
End If
' or
frm.SomeProperty = item
As you see, you can pass an object that you can store in combo box. It doesn't have to be string.

Updating and changing the data source of combobox VB.Net

I'm creating a multiclient-server application (chat room). I 'store' every connection (actually the connection-objects) in a hashtable. I also want to see and select one client from a combobox. I managed to bind the combobox to the hashtable but when I try to update the hashtable and then the combobox it changes every item to:
System.Collections.DictionaryEntry
to
user_selector is the combobox
registered_clients is the hashtable(clients connected through tcp to the server)
DB_clients is another hashtable (it takes users from a database).The combobox will show users from this hashtable.
The Form Code
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
form = Me ''The variable is used in the module
conn_listener.Start()
conn_listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf new_client), conn_listener)
End Sub
Private Sub new_client(ByVal ar As IAsyncResult)
total_logged_clients += 1
temp_client = New Client(conn_listener.EndAcceptTcpClient(ar))
AddHandler temp_client.Connected, AddressOf Connected
AddHandler temp_client.Disconnected, AddressOf Disconnected
AddHandler temp_client.New_Message, AddressOf New_Message
Update_Log_Data("New user found & added. Waiting for details...")
conn_listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf new_client), conn_listener) ''Loop
End Sub
Private Sub Connected(ByVal user As Client_Info)
total_registered_clients += 1
registered_clients.Add(user.ID, temp_client) '' Register each client based on its ID (in the hashtable)
Update_Log_Data("Confirmed client:" & user.Computer_Name & "," & user.ID)
RaiseEvent Update_GUI() ''Function from the module
End Sub
Private Sub Disconnected(ByVal user As Client_Info, ByVal reason As System.Exception)
Dim class_for_disposal As Client
total_logged_clients -= 1
If Not user.Connection_Status = Enum_Connection_Status.NO_INFO Then
total_registered_clients -= 1
End If
''Dispose this class
If registered_clients.ContainsKey(user.ID) Then
class_for_disposal = registered_clients.Item(user.ID)
registered_clients.Remove(user.ID)
class_for_disposal.Dispose()
End If
Update_Log_Data("Deconnected:" & user.Computer_Name & "," & user.ID & " because:" & reason.Message, 1)
RaiseEvent Update_GUI()
End Sub
Private Sub user_selector_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles user_selector.SelectionChangeCommitted
Dim temp_selection As New DictionaryEntry
temp_selection = user_selector.SelectedItem
If registered_clients.ContainsKey(temp_selection.Key) Then
'' If the selected user is in the hastable then
''set "selected_user" to the object created by the user
'' With this object I can sendand receive from the selected user.
selected_user = registered_clients.Item(temp_selection.Key)
Else
selected_user = Nothing
End If
''Update_Data_GUI()
RaiseEvent Update_GUI()
End Sub
The Module
Private Sub Update_GUI() Handles form.Update_GUI
''Called often by controls
Interface_DB_clients()
Interface_bottom_conn_status()
End Sub
Private Sub Interface_bottom_conn_status()
With form
If .bottom_band.InvokeRequired Then
.Invoke(New Repeat(AddressOf Interface_bottom_conn_status))
Else
If selected_user Is Nothing Then
.bottom_client_status.ForeColor = Color.Red
.bottom_client_status.Text = "Offline"
Else
.bottom_client_status.ForeColor = Color.Green
.bottom_client_status.Text = "Online"
End If
End If
End With
End Sub
Private Sub Interface_DB_clients()
Dim preserve_item As DictionaryEntry
Dim bind As New BindingSource
With form
If .user_selector.InvokeRequired Then
.Invoke(New Repeat(AddressOf Interface_DB_clients))
Else
'' Here it's being made the refresh
preserve_item = .user_selector.SelectedItem
bind.DataSource = DB_clients
.user_selector.DataSource = Nothing ''clear first
.user_selector.DataSource = bind
.user_selector.ValueMember = "Value"
'' Selected old value
.user_selector.SelectedItem = preserve_item
End If
End With
End Sub
I've created special classes for the clients and that's why you can see properties like user.id and structures like Header_Info and Client_Info. I tried overlaping the data sources ,here
.user_selector.DataSource = Nothing ''clear first
.user_selector.DataSource = bind
by simply removing the .user_selector.DataSource = Nothing part.It worked when I added a new element but what if I remove a user? And why is it showing that error?
Where is the problem?

vb.net Find Form

In the Windows, the native Notepad program has a find form. Basically When the user types and hits 'Find Next', the program proceeds to find the text while keeping the focus on the Find form. This way the user can keep hitting the 'Enter' key or the button and still have the text highlighted while the form is focused.
My problem is that I have a different form for the "Search" feature and whenever the user hits "Enter" the text is found and the focus is set on the TextBox but when the user hits "Enter" again, the text gets edited because of the focus.
Currently, I'm using Regex to do this and I am using a WPF TextBox using HostElement:
Private Function GetRegExpression() As Regex
Dim result As Regex
Dim regExString As [String]
regExString = txtbx_Find.Text
If matchCaseCheckBox.Checked Then
result = New Regex(regExString)
Else
result = New Regex(regExString, RegexOptions.IgnoreCase)
End If
Return result
End Function
Private Sub FindText()
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
If isFirstFind Then
regex = GetRegExpression()
match = regex.Match(TheTextBox.Text)
isFirstFind = False
Else
match = regex.Match(TheTextBox.Text, match.Index + 1)
End If
If match.Success Then
Dim row As Integer = TheTextBox.GetLineIndexFromCharacterIndex(TheTextBox.CaretIndex)
MoveCaretToLine(TheTextBox, row + 1)
TheTextBox.SelectionStart = match.Index
TheTextBox.SelectionLength = match.Length
TheTextBox.Focus()
Me.Focus()
Else
MessageBox.Show([String].Format("Cannot find ""{0}"" ", txtbx_Find.Text), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
isFirstFind = True
End If
End Sub
Private Sub btn_FindNext_Click(sender As Object, e As EventArgs) Handles btn_FindNext.Click
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
FindText()
'theTextBox.Focus()
End Sub
I want it to be just like Notepad where the user hits "Enter" and keeps focus on the Find Form while selecting the text. How can this be achieved?
I think you should catch "keyup" event of your form like this :
Class MainWindow
Private Sub Window_KeyUp(sender As System.Object, e As System.Windows.Input.KeyEventArgs) Handles MyBase.KeyUp
If e.Key = Key.Enter Then
FindNext()
End If
End Sub
Private Sub btn_FindNext_Click(sender As Object, e As EventArgs) Handles btn_FindNext.Click
FindText()
End Sub
Private Sub FindNext()
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
FindText()
'theTextBox.Focus()
End Sub
End Class