Reputation: 95
I have 3 Forms namely MainForm, Form1 and Form2. MainForm hosts Form1 in a Panel
. On Clicking a button
in MainForm, I am opening Form2 using ShowDialog()
method. Now I have a treeview
in Form2
. Now I want to pass the nodes selected in Form2 back to a combobox
in Form1. How can this be achieved? I have tried Form1.Activate()
in Form2 but the code is not hitting Activate
method in Form1.
Also I am using Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text)
but I cannot see any items in ComboBox once Form2 is closed. What am I missing here?
Below is the code for better understanding.
MainForm
public Class MainForm
private Sub OpenChildForm(childForm As Form)
panelFormContainer.Controls.Add(childForm)
childForm.Dock = DockStyle.Fill
childForm.Show()
End Sub
private sub MainForm_OnLoad(sender As Object, e as EventArgs) Handles Me.Load
'Adding child form to a Panel in Main Form
OpenChildForm(new Form1())
End Sub
'Open Form 2 on Button Click
private sub btnOpenForm3_Click(sender As Object, e as EventArgs) Handles btnOpenForm3.Click
Form2.ShowDialog()
End Sub
End Class
Form2 - Child Form Opened by button click in MainForm
Public Class Form2
'Click back button to go back to Main Form which is already having Form1 as child
Private Sub btnBack_Click(sender As Object, e As EventArgs)
Me.Close()
Form1.Activate()
End Sub
'Click a Button to Add Selected Treeview node to Combo in Form1
Private Sub btnAdd_Click(sender As Object, e As EventArgs) btnAdd.Click
Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text)
End Sub
End Class
Updated: I have updated the code but still not getting anything in ComboBox of Child Form1
MainForm
Public Class Form1
Private currentChildForm As Form = Nothing
Private ownerForm As Form = Nothing
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
OpenChildForm(New ChildForm1())
End Sub
Private Sub OpenChildForm(childForm As Form)
If currentChildForm IsNot Nothing Then
currentChildForm.Close()
End If
childForm.TopLevel = False
childForm.FormBorderStyle = FormBorderStyle.None
panelFormContainer.Controls.Clear()
panelFormContainer.Controls.Add(childForm)
childForm.Dock = DockStyle.Fill
childForm.BringToFront()
childForm.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dialogForm As ChildForm2 = New ChildForm2()
'
Dim result = dialogForm.ShowDialog()
If result = DialogResult.OK Then
AddHandler ChildForm2.Button1.Click, AddressOf ChildForm1.objForm2_Passvalue
End If
End Sub
End Class
ChildForm1 which is hosted in MainForm
Public Class ChildForm1
Private Sub ChildForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If ComboBox1.Items.Count > 0 Then
ComboBox1.SelectedIndex = 0
End If
End Sub
Private Sub ChildForm1_Activated(sender As Object, e As EventArgs) Handles Me.Activated
End Sub
Public Sub objForm2_Passvalue(sender As Object, e As EventArgs)
Me.ComboBox1.Items.Add(PageDetail.PageTitle)
End Sub
End Class
ChildForm2 -- Which is opened as Dialog
Public Class ChildForm2
Private Sub ChildForm2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView1.ExpandAll()
Button1.DialogResult = DialogResult.OK
End Sub
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PageDetail.PageTitle = TreeView1.SelectedNode.Text
Me.Close()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Close()
End Sub
End Class
PageDetail: Class used to get and set data
Public NotInheritable Class PageDetail
Private Shared pageTitleValue As String
Public Shared Property PageTitle As String
Get
Return pageTitleValue
End Get
Set(value As String)
pageTitleValue = value
End Set
End Property
End Class
Upvotes: 0
Views: 970
Reputation: 5009
The following shows multiple ways to pass data between forms. In the code below, I show how to retrieve data from a child form (ChildForm2) using a function, a property, or an event. This data is passed back to the parent form (MainForm). Once the parent form (MainForm) receives the data, it sends the data to a different child form (ChildForm1). Data can be sent from the parent form (MainForm) to the child form (ChildForm1) using one of the constructors, a method, or a property.
Note: MainForm
is the startup form and is the parent to both ChildForm1
and ChildForm2
(ie: instances of both ChildForm1
and ChildForm2
are created in MainForm)
Create a new project
VS 2019:
Open Solution Explorer
Add Form (Name: ChildForm1.vb)
Label
(Text: "Select One")ComboBox
(Name: ComboBox1)In Solution Explorer, right click ChildForm1.vb, and select View Code
ChildForm1.vb
Public Class ChildForm1
Public WriteOnly Property PageTitle As String
Set(value As String)
'populate ComboBox
PopulateComboBox(value)
End Set
End Property
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Sub New(pageTitle As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
PopulateComboBox(pageTitle)
End Sub
Sub New(pageTitles As List(Of String))
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
PopulateComboBox(pageTitles)
End Sub
Private Sub ChildForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub PopulateComboBox(pageTitle As String)
'create new instance
Dim pageTitles As New List(Of String)
'add
pageTitles.Add(pageTitle)
'populate ComboBox
PopulateComboBox(pageTitles)
End Sub
Public Sub PopulateComboBox(pageTitles As List(Of String))
'remove existing data from ComboBox
ComboBox1.Items.Clear()
ComboBox1.Text = String.Empty
For Each pTitle In pageTitles
'add
ComboBox1.Items.Add(pTitle)
Next
If ComboBox1.Items.Count = 1 Then
'if only 1 item exists, select it
ComboBox1.SelectedIndex = 0
End If
End Sub
End Class
Add a Form (name: ChildForm2.vb)
In Solution Explorer, right click ChildForm2.vb, and select View Code
ChildForm2.vb
Public Delegate Sub PassValueHandler(ByVal strValue As String)
Public Class ChildForm2
Public Event PassValue As PassValueHandler
Public ReadOnly Property PageTitle
Get
Return TreeView1.SelectedNode.Text
End Get
End Property
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PopulateTreeView()
TreeView1.ExpandAll()
End Sub
Public Function GetPageTitle() As String
Return PageTitle
End Function
Private Sub PopulateTreeView()
'ToDo: Replace this method with code to populate your TreeView
TreeView1.Nodes.Clear()
'Parent 1
Dim node1 As TreeNode = New TreeNode("Parent 1")
Dim childNode1 As TreeNode = New TreeNode("Child Node 1")
'add
node1.Nodes.Add(childNode1)
'add
TreeView1.Nodes.Add(node1)
'Parent 2
Dim node2 As TreeNode = New TreeNode("Parent 2")
Dim childNode2 As TreeNode = New TreeNode("Child Node 2")
'add
node2.Nodes.Add(childNode2)
'add
TreeView1.Nodes.Add(node2)
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'raise event
RaiseEvent PassValue(TreeView1.SelectedNode.Text)
'set value
Me.DialogResult = DialogResult.OK
'close
Me.Close()
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
'set value
Me.DialogResult = DialogResult.Cancel
'close
Me.Close()
End Sub
End Class
Rename Form1 to MainForm
MainForm
In Solution Explorer, right click MainForm.vb, and select View Code
In the code below, I've written it in such a way that it allows one to choose different options for both retrieving data from a child form, as well as, multiple options for sending data to a child form.
MainForm.vb
Public Class MainForm
Private dialogForm As ChildForm2 = Nothing
Private currentChildForm As Form = Nothing
Private ownerForm As Form = Nothing
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'open Form
OpenChildForm(New ChildForm1())
End Sub
Private Sub OpenChildForm(ByRef childForm As Form)
If currentChildForm IsNot Nothing Then
currentChildForm.Dispose()
currentChildForm = Nothing
End If
'set value
currentChildForm = childForm
'set properties
childForm.Dock = DockStyle.Fill
childForm.TopLevel = False
childForm.FormBorderStyle = FormBorderStyle.None
'remove existing controls
panelFormContainer.Controls.Clear()
'add
panelFormContainer.Controls.Add(childForm)
'show
childForm.Show()
End Sub
Private Sub PopulateChildForm1ComboBox(pageTitle As String)
If currentChildForm.GetType() = ChildForm1.GetType() Then
'currentChildForm is an instance of ChildForm1
'create reference
Dim frm = CType(currentChildForm, ChildForm1)
'option 1 - populate ComboBox by calling method
frm.PopulateComboBox(pageTitle)
'option 2 - populate ComboBox by setting property
'frm.PageTitle = PageDetail.PageTitle
End If
End Sub
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'ToDo: Replace this method with code from Option 1, Option 2, or Option 3 below
...
End Sub
Private Sub DialogForm_BtnAdd_Click(sender As Object, e As System.EventArgs)
'option 1 - get page title from property
PageDetail.PageTitle = dialogForm.PageTitle
'option 2 - get page title by calling function
'PageDetail.PageTitle = dialogForm.GetPageTitle()
'populate ComboBox
PopulateChildForm1ComboBox(PageDetail.PageTitle)
End Sub
Private Sub DialogForm_PassValue(e As String)
'set value
PageDetail.PageTitle = e
'populate ComboBox
PopulateChildForm1ComboBox(e)
End Sub
End Class
Choose one of the following options for retrieving data from ChildForm2. Replace the method btnOpenChildForm2_Click
(in MainForm.vb) with the code listed below.
Option 1 (DialogResult.OK)
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'show dialog
If dialogForm.ShowDialog() = DialogResult.OK Then
PageDetail.PageTitle = dialogForm.PageTitle
'populate ComboBox
PopulateChildForm1ComboBox(PageDetail.PageTitle)
End If
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 1
, the code for DialogForm_BtnAdd_Click
and DialogForm_PassValue
(in MainForm.vb) isn't used, so both of these methods can be removed.
Option 2 (subscribe to btnAdd 'Click' event)
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'subscribe to events (add event handlers)
AddHandler dialogForm.btnAdd.Click, AddressOf DialogForm_BtnAdd_Click
'show dialog
dialogForm.ShowDialog()
'unsubscribe from events (remove event handlers)
RemoveHandler dialogForm.btnAdd.Click, AddressOf DialogForm_BtnAdd_Click
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 2
, the code for DialogForm_PassValue
(in MainForm.vb) isn't used, so method DialogForm_PassValue
can be removed.
Option 3 (subscribe to event 'PassValue')
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'subscribe to events (add event handlers)
AddHandler dialogForm.PassValue, AddressOf DialogForm_PassValue
'show dialog
dialogForm.ShowDialog()
'unsubscribe from events (remove event handlers)
RemoveHandler dialogForm.PassValue, AddressOf DialogForm_PassValue
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 3
, the code for DialogForm_BtnAdd_Click
(in MainForm.vb) isn't used, so method DialogForm_BtnAdd_Click
can be removed.
Here's a demo:
Resources:
Upvotes: 1
Reputation: 5009
Rather than placing a Form
on a panel, you might consider creating a UserControl
and placing that on the panel. The following show how to pass data from a Form (Form2) that is shown using ShowDialog()
to a UserControl (UserControl1) that exists on a different form (MainForm).
Note: MainForm
is the startup form. If desired, the UserControl can be replaced with a Form.
Create a new project
VS 2019:
In VS menu, click File
Select New
Select Project
Select Windows Forms App (.NET Framework)
Click Next
Enter desired project name
Click Create
Open Solution Explorer
Add UserControl (Name: UserControl1.vb)
In Solution Explorer, right-click <project name>, select Add
Select User Control (Windows Forms)... (name: UserControl1.vb)
Add a Label
(Text: "Select One")
Add a ComboBox
(Name: ComboBox1)
UserControl1.vb
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub PopulateComboBox(value As String)
'remove existing data from ComboBox
ComboBox1.Items.Clear()
ComboBox1.Text = String.Empty
'add
ComboBox1.Items.Add(value)
If ComboBox1.Items.Count = 1 Then
'if only 1 item exists, select it
ComboBox1.SelectedIndex = 0
End If
End Sub
End Class
Note: If using a Form
instead of a UserControl
, add the code for PopulateComboBox
to your form.
Add a Form (name: Form2.vb)
In Solution Explorer, right-click <project name>, select Add
Select Form (Windows Forms)... (Name: Form2.vb)
Add a Label
Add a TreeView (name: TreeView1)
Add a Button (Name: btnAdd; Text: Add)
Double-click "btnAdd" to add the Click event handler
Add a Button (Name: btnCancel; Text: Cancel)
Double-click "btnCancel" to add the Click event handler
In Solution Explorer, right click Form2.vb, and select View Code
Form2.vb
Imports System.IO
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PopulateTreeView()
End Sub
'ToDo: Replace this function with one that returns the desired data
Public Function GetSelectedValue() As String
Return TreeView1.SelectedNode.Text
End Function
Private Sub PopulateTreeView()
'ToDo: Replace this code with your desired code to populate the TreeView
'clear
TreeView1.Nodes.Clear()
Dim topNode As TreeNode = New TreeNode("Computer")
TreeView1.Nodes.Add(topNode)
Dim logicalDrives As String() = Directory.GetLogicalDrives()
If logicalDrives IsNot Nothing Then
For Each drive As String In logicalDrives
Debug.WriteLine("drive: " & drive.ToString())
Try
Dim dirInfo As DirectoryInfo = New DirectoryInfo(drive)
TreeView1.Nodes.Add(New TreeNode(drive))
Catch ex As Exception
'do nothing
End Try
Next
End If
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'in MainForm we'll subscribe to the Add button Click event and retrieve the data by calling function "GetSelectedValue", so all we have to do here is close the form
Me.Close()
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class
Rename Form1 to MainForm
Build Project
MainForm
Add a panel to MainForm (Name: panel1)
In Toolbox (View => Toolbox), expand: <solution name> Components
Drag UserControl1 onto panel1 on MainForm
Add Button (Name: btnOpenForm2; Text: Open Form2)
Double-click "btnOpenForm2" to add the Click event handler
In Solution Explorer, right click MainForm.vb, and select View Code
MainForm.vb
Public Class MainForm
Private frm2 As Form2 = Nothing
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btnOpenForm2_Click(sender As Object, e As EventArgs) Handles btnOpenForm2.Click
If frm2 Is Nothing Then
'create new instance
frm2 = New Form2()
End If
'subscribe to events (add event handlers)
AddHandler frm2.btnAdd.Click, AddressOf Frm2BtnAdd_Click
'show dialog
frm2.ShowDialog()
'the code below will execute after frm2 is closed
'unsubscribe from events (remove event handlers)
RemoveHandler frm2.btnAdd.Click, AddressOf Frm2BtnAdd_Click
'dispose
frm2.Dispose()
frm2 = Nothing
End Sub
Private Sub Frm2BtnAdd_Click(sender As Object, e As System.EventArgs)
'call method to populate ComboBox
'UserControl11.PopulateComboBox(frm2.GetSelectedValue())
'call function to get data
Dim userSelection As String = frm2.GetSelectedValue()
'call method to populate ComboBox
UserControl11.PopulateComboBox(userSelection)
End Sub
End Class
Here's a demonstration:
Resources
Upvotes: 1