在子表单中发送数据
Send data within Child Forms
我有 3 个窗体,即 MainForm、Form1 和 Form2。 MainForm 在 Panel
中承载 Form1。单击 MainForm 中的 button
时,我将使用 ShowDialog()
方法打开 Form2。现在我在 Form2
中有一个 treeview
。 现在我想将 Form2 中选择的节点传递回 Form1 中的 combobox
。如何实现?我在 Form2 中尝试了 Form1.Activate()
,但代码没有命中 Form1 中的 Activate
方法。
我也在使用 Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text)
,但是一旦关闭 Form2,我就看不到 ComboBox 中的任何项目。我在这里错过了什么?
为了更好的理解下面的代码。
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
已更新:我已经更新了代码,但仍然没有在 Child Form1 的 ComboBox 中得到任何东西
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
与其在面板上放置 Form
,不如考虑创建一个 UserControl
并将其放置在面板上。下面显示如何将数据从使用 ShowDialog()
显示的窗体 (Form2) 传递到存在于不同窗体 (MainForm) 上的用户控件 (UserControl1)。
注意:MainForm
为启动形式。如果需要,可以将 UserControl 替换为 Form。
新建项目
VS 2019:
在 VS 菜单中,单击 文件
Select 新建
Select 项目
Select Windows 表单应用程序 (.NET Framework)
点击下一步
输入所需的项目名称
单击创建
打开解决方案资源管理器
- 在VS菜单中,select查看
- Select 解决方案资源管理器
添加用户控件(名称:UserControl1.vb)
在解决方案资源管理器中,右键单击 <项目名称>,select 添加
Select 用户控件(Windows 表单)...(名称:UserControl1.vb)
添加一个Label
(文本:“Select一个”)
添加一个ComboBox
(名称: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
注意:如果使用 Form
而不是 UserControl
,请将 PopulateComboBox
的代码添加到您的表单中。
添加表格(名称:Form2.vb)
在解决方案资源管理器中,右键单击 <项目名称>,select 添加
Select表格(Windows表格)...(姓名:Form2.vb)
添加标签
添加一个TreeView(名称:TreeView1)
添加一个按钮(名称:btnAdd;文字:添加)
双击“btnAdd”添加点击事件处理程序
添加一个按钮(名称:btnCancel;文字:取消)
双击“btnCancel”添加点击事件处理程序
在解决方案资源管理器中,右键单击 Form2.vb,然后 select 查看代码
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
将 Form1 重命名为 MainForm
- 在解决方案资源管理器中,右键单击 Form1.vb
- Select 重命名
- 输入MainForm.vb
- 当提示“您正在重命名一个文件。您是否也想在此项目中对代码元素 'Form1' 的所有引用执行重命名?单击 是
- 在属性 Window 中,为“MainForm”设置 Text =“MainForm”
构建项目
- 在解决方案资源管理器中,右键单击 <项目名称>,select Build
主窗体
向 MainForm 添加面板(名称:panel1)
在工具箱(视图 => 工具箱)中,展开:<解决方案名称> 组件
将 UserControl1 拖到 MainForm
上的 panel1 上
添加按钮(名称:btnOpenForm2;文本:Open Form2)
双击“btnOpenForm2”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 MainForm.vb,然后 select 查看代码
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
演示一下:
资源
- How to populate a treeview from a list of objects
下面展示了在表单之间传递数据的多种方式。在下面的代码中,我展示了如何使用函数、属性 或事件从子窗体 (ChildForm2) 检索数据。此数据被传递回父窗体 (MainForm)。一旦父窗体 (MainForm) 接收到数据,它将数据发送到不同的子窗体 (ChildForm1)。可以使用构造函数之一、方法或 属性.
将数据从父窗体 (MainForm) 发送到子窗体 (ChildForm1)
注意:MainForm
是启动表单并且是 ChildForm1
和 ChildForm2
的父级(即:ChildForm1
和 ChildForm2
是在 MainForm 中创建的)
新建项目
VS 2019:
- 在 VS 菜单中,单击 文件
- Select 新建
- Select 项目
- Select Windows 表单应用程序 (.NET Framework)
- 点击下一步
- 输入所需的项目名称
- 单击创建
打开解决方案资源管理器
- 在 VS 菜单中,select 查看
- Select 解决方案资源管理器
添加表格(姓名:ChildForm1.vb)
- 在解决方案资源管理器中,右键单击 <项目名称>,select 添加
- Select表格(Windows表格)...(姓名:ChildForm1.vb)
- 添加一个
Label
(文本:“Select一个”)
- 添加一个
ComboBox
(名称:ComboBox1)
在解决方案资源管理器中,右键单击 ChildForm1.vb,然后 select 查看代码
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
添加表单(名称:ChildForm2.vb)
- 在解决方案资源管理器中,右键单击 <项目名称>,select 添加
- Select表格(Windows表格)...(姓名:ChildForm2.vb)
- 添加标签
- 添加一个TreeView(名称:TreeView1)
- 添加一个按钮(名称:btnAdd;文字:添加)
- 双击“btnAdd”添加点击事件处理程序
- 添加一个按钮(名称:btnCancel;文字:取消)
- 双击“btnCancel”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 ChildForm2.vb,然后 select 查看代码
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
将 Form1 重命名为 MainForm
- 在解决方案资源管理器中,右键单击 Form1.vb
- Select 重命名
- 输入MainForm.vb
- 当系统提示“您正在重命名一个文件。您是否也想在此项目中对代码元素 'Form1' 的所有引用执行重命名?单击 是
- 在属性 Window 中,为“MainForm”设置 Text =“MainForm”
主窗体
- 向 MainForm 添加面板(名称:panelFormContainer)
- 添加按钮(名称:btnOpenChildForm2;文本:Open ChildForm2)
- 双击“btnOpenChildForm2”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 MainForm.vb,然后 select 查看代码
在下面的代码中,我以这样一种方式编写它,它允许人们选择不同的选项来从子表单中检索数据,以及将数据发送到子表单的多个选项。
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
选择以下选项之一以从 ChildForm2 检索数据。用下面列出的代码替换方法 btnOpenChildForm2_Click
(在 MainForm.vb 中)。
选项 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
注意:当使用Option 1
时,DialogForm_BtnAdd_Click
和DialogForm_PassValue
的代码(在MainForm.vb中)不是使用,所以这两种方法都可以删除。
选项 2(订阅 btnAdd 'Click' 事件)
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
注意:当使用Option 2
时,没有使用DialogForm_PassValue
的代码(在MainForm.vb中),所以方法DialogForm_PassValue
可以删除。
选项 3(订阅事件 '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
注意:当使用Option 3
时,没有使用DialogForm_BtnAdd_Click
的代码(在MainForm.vb中),所以方法DialogForm_BtnAdd_Click
可以删除。
这是一个演示:
资源:
- Form.ShowDialog
- Form.Show
- How to populate a treeview from a list of objects
我有 3 个窗体,即 MainForm、Form1 和 Form2。 MainForm 在 Panel
中承载 Form1。单击 MainForm 中的 button
时,我将使用 ShowDialog()
方法打开 Form2。现在我在 Form2
中有一个 treeview
。 现在我想将 Form2 中选择的节点传递回 Form1 中的 combobox
。如何实现?我在 Form2 中尝试了 Form1.Activate()
,但代码没有命中 Form1 中的 Activate
方法。
我也在使用 Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text)
,但是一旦关闭 Form2,我就看不到 ComboBox 中的任何项目。我在这里错过了什么?
为了更好的理解下面的代码。
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
已更新:我已经更新了代码,但仍然没有在 Child Form1 的 ComboBox 中得到任何东西
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
与其在面板上放置 Form
,不如考虑创建一个 UserControl
并将其放置在面板上。下面显示如何将数据从使用 ShowDialog()
显示的窗体 (Form2) 传递到存在于不同窗体 (MainForm) 上的用户控件 (UserControl1)。
注意:MainForm
为启动形式。如果需要,可以将 UserControl 替换为 Form。
新建项目
VS 2019:
在 VS 菜单中,单击 文件
Select 新建
Select 项目
Select Windows 表单应用程序 (.NET Framework)
点击下一步
输入所需的项目名称
单击创建
打开解决方案资源管理器
- 在VS菜单中,select查看
- Select 解决方案资源管理器
添加用户控件(名称:UserControl1.vb)
在解决方案资源管理器中,右键单击 <项目名称>,select 添加
Select 用户控件(Windows 表单)...(名称:UserControl1.vb)
添加一个
Label
(文本:“Select一个”)添加一个
ComboBox
(名称: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
注意:如果使用 Form
而不是 UserControl
,请将 PopulateComboBox
的代码添加到您的表单中。
添加表格(名称:Form2.vb)
在解决方案资源管理器中,右键单击 <项目名称>,select 添加
Select表格(Windows表格)...(姓名:Form2.vb)
添加标签
添加一个TreeView(名称:TreeView1)
添加一个按钮(名称:btnAdd;文字:添加)
双击“btnAdd”添加点击事件处理程序
添加一个按钮(名称:btnCancel;文字:取消)
双击“btnCancel”添加点击事件处理程序
在解决方案资源管理器中,右键单击 Form2.vb,然后 select 查看代码
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
将 Form1 重命名为 MainForm
- 在解决方案资源管理器中,右键单击 Form1.vb
- Select 重命名
- 输入MainForm.vb
- 当提示“您正在重命名一个文件。您是否也想在此项目中对代码元素 'Form1' 的所有引用执行重命名?单击 是
- 在属性 Window 中,为“MainForm”设置 Text =“MainForm”
构建项目
- 在解决方案资源管理器中,右键单击 <项目名称>,select Build
主窗体
向 MainForm 添加面板(名称:panel1)
在工具箱(视图 => 工具箱)中,展开:<解决方案名称> 组件
将 UserControl1 拖到 MainForm
上的 panel1 上添加按钮(名称:btnOpenForm2;文本:Open Form2)
双击“btnOpenForm2”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 MainForm.vb,然后 select 查看代码
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
演示一下:
资源
- How to populate a treeview from a list of objects
下面展示了在表单之间传递数据的多种方式。在下面的代码中,我展示了如何使用函数、属性 或事件从子窗体 (ChildForm2) 检索数据。此数据被传递回父窗体 (MainForm)。一旦父窗体 (MainForm) 接收到数据,它将数据发送到不同的子窗体 (ChildForm1)。可以使用构造函数之一、方法或 属性.
将数据从父窗体 (MainForm) 发送到子窗体 (ChildForm1)注意:MainForm
是启动表单并且是 ChildForm1
和 ChildForm2
的父级(即:ChildForm1
和 ChildForm2
是在 MainForm 中创建的)
新建项目
VS 2019:
- 在 VS 菜单中,单击 文件
- Select 新建
- Select 项目
- Select Windows 表单应用程序 (.NET Framework)
- 点击下一步
- 输入所需的项目名称
- 单击创建
打开解决方案资源管理器
- 在 VS 菜单中,select 查看
- Select 解决方案资源管理器
添加表格(姓名:ChildForm1.vb)
- 在解决方案资源管理器中,右键单击 <项目名称>,select 添加
- Select表格(Windows表格)...(姓名:ChildForm1.vb)
- 添加一个
Label
(文本:“Select一个”) - 添加一个
ComboBox
(名称:ComboBox1)
在解决方案资源管理器中,右键单击 ChildForm1.vb,然后 select 查看代码
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
添加表单(名称:ChildForm2.vb)
- 在解决方案资源管理器中,右键单击 <项目名称>,select 添加
- Select表格(Windows表格)...(姓名:ChildForm2.vb)
- 添加标签
- 添加一个TreeView(名称:TreeView1)
- 添加一个按钮(名称:btnAdd;文字:添加)
- 双击“btnAdd”添加点击事件处理程序
- 添加一个按钮(名称:btnCancel;文字:取消)
- 双击“btnCancel”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 ChildForm2.vb,然后 select 查看代码
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
将 Form1 重命名为 MainForm
- 在解决方案资源管理器中,右键单击 Form1.vb
- Select 重命名
- 输入MainForm.vb
- 当系统提示“您正在重命名一个文件。您是否也想在此项目中对代码元素 'Form1' 的所有引用执行重命名?单击 是
- 在属性 Window 中,为“MainForm”设置 Text =“MainForm”
主窗体
- 向 MainForm 添加面板(名称:panelFormContainer)
- 添加按钮(名称:btnOpenChildForm2;文本:Open ChildForm2)
- 双击“btnOpenChildForm2”添加 Click 事件处理程序
在解决方案资源管理器中,右键单击 MainForm.vb,然后 select 查看代码
在下面的代码中,我以这样一种方式编写它,它允许人们选择不同的选项来从子表单中检索数据,以及将数据发送到子表单的多个选项。
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
选择以下选项之一以从 ChildForm2 检索数据。用下面列出的代码替换方法 btnOpenChildForm2_Click
(在 MainForm.vb 中)。
选项 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
注意:当使用Option 1
时,DialogForm_BtnAdd_Click
和DialogForm_PassValue
的代码(在MainForm.vb中)不是使用,所以这两种方法都可以删除。
选项 2(订阅 btnAdd 'Click' 事件)
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
注意:当使用Option 2
时,没有使用DialogForm_PassValue
的代码(在MainForm.vb中),所以方法DialogForm_PassValue
可以删除。
选项 3(订阅事件 '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
注意:当使用Option 3
时,没有使用DialogForm_BtnAdd_Click
的代码(在MainForm.vb中),所以方法DialogForm_BtnAdd_Click
可以删除。
这是一个演示:
资源:
- Form.ShowDialog
- Form.Show
- How to populate a treeview from a list of objects