在VB.net中将值从子窗体传递到MDI父窗体

4

我有一个简单的联系人簿。该应用程序具有一个主窗口,即MDI表单。当使用“添加联系人”表单添加联系人时,我希望在父窗口状态栏中显示一个简单的反馈消息,说明联系人已成功添加。

以下是子窗口加载:

Private Sub addButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles addButton.Click
    Dim af As New addForm
    af.MdiParent = Me
    af.Show()
End Sub

问题在于父窗体实际上是一个MDI父窗体,而“添加联系人”窗体是通过.Show()而不是.ShowDialog()启动的,因此我无法存储任何可由启动子窗体使用的返回值来执行操作。
有没有一种方法可以从子窗体传递值给MDI父窗体?以下是子窗体正在执行的操作:
Private Sub addButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles addButton.Click

    Dim contact = <contact>
                      <quickName><%= quickNameTextBox.Text %></quickName>
                      <firstName><%= firstNameTextBox.Text %></firstName>
                      <lastName><%= lastNameTextBox.Text %></lastName>
                      <email><%= emailTextBox.Text %></email>
                      <website><%= websiteTextBox.Text %></website>
                      <telephone><%= telephoneTextBox.Text %></telephone>
                      <mobile><%= mobileTextBox.Text %></mobile>
                  </contact>

    Dim contactList = XDocument.Load("contactList.xml")

    contactList.Elements()(0).Add(contact)
    contactList.Save("contactList.xml")
    //something here to trigger the status update in the parent?
    //trivia: SO doesn't support VB single-quote comments...
    Me.Close()

End Sub

顺便说一句,我很不擅长标记东西...所以任何想重新标记这个问题的人都非常欢迎。

6个回答

6
我会处理这个问题的方式是,在子控件上创建一个自定义事件。然后在父控件上处理该事件。
首先,在子控件中定义事件(例如,定义自己的事件):
Public Event EVENTNAME(ByVal sender as Object, ByVal ValueToReturn As String)

然后,在数据准备好传递时,在子控件上引发事件。
RaiseEvent EVENTNAME(Me, txtBoxWithReturnValue.Text)

一旦你完成了这个步骤,在父表单上,现在你可以处理自定义事件。为此,你需要添加一个监听器来“监听”事件何时触发:
AddHandler CONTROLNAME.EVENTNAME, AddressOf EVENTNAME

然后,您可以编写一个程序来处理父窗体中的这个新事件:
Private Sub FUNCTIONAME(ByVal sender As System.Object, ByVal ValueToReturn as String) Handles CONTROLNAME.EVENTNAME

'Code to handle data here

End Sub

抱歉,但是在父表单中我应该把处理程序放在哪里?CONTROLNAME指的是什么? - Mussnoon
你需要在创建子窗体后立即放置处理程序。这与此帖子类似:http://stackoverflow.com/questions/1774386/how-to-declare-events-on-class-library-dll-and-catch-them-on-form/1775453#1775453 - Walter

1
在VB.NET中,您可以使用[My]命名空间。My.Forms.[您的MDI表单的名称],所以...如果您的主要表单名为MdiMain,则可以执行如下操作。
My.Forms.MdiMain.lblStatus = "X"

我所有的子窗体都继承自同一个基类,而该类只有一个属性,返回 My.Forms.MdiMain。我称之为 MdiParentForm。这样,我可以在任何窗体上只需输入 Me.MdiParentForm,就能轻松地找到父窗体。(少打字)


1

这是最简单的答案,没有事件!

情况:1个MdiParent表单(Form1)和2个子控件表单(Control1Form和Control2Form)。在启动时,在MdiParent中创建子控件(control1和control2)。

Form1在StatusStrip中有一个名为StatusLabel的标签。 Control2有一个名为Button1的按钮。

目标:当单击Control2的按钮时,Control2将写入到control1的标题和Form1的StatusLabel。

PARTIAL CODE

FORM1
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
control1 = New Control1Form
control2 = New Control2Form
control1.MdiParent = Me
control1.Show()
control2.MdiParent = Me
control2.Show()
End Sub
End Class


CONTROL2FORM
Public Class Control2Form
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
'Title of Control1
CType(Me.ParentForm, Form1).control1.Text = "Title bar text"
'Status Strip Label
CType(Me.ParentForm, Form1).StatusLabel.Text = "Status Strip Text"
End Sub
End Class

完成了!希望能有所帮助。


0
在 MDI 中创建一个控制器类,并将其作为参数传递给子窗体。在 Me.Close() 之前,将 contactlist 分配给控制器上的属性。
需要更好地分离数据和 GUI。 有关 Model-View-Controller 模式的更多信息,请单击 此处

0

Jon的回答虽然很有帮助,但是它不完整。缺少的部分可能会让像我这样的新手感到困惑。

与其像我最初那样使addForm变暗,一个需要使用WithEvents关键字在类级别创建addForm的实例,然后在事件处理程序中使用此实例来加载表单。

Private WithEvents oneAddForm As New addForm //create a new instance of addForm

Private Sub addButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles addButton.Click
    oneAddForm.MdiParent = Me
    oneAddForm.Show()
End Sub
//using this instance to load the form...

Private Sub updateStatus(ByVal sender As System.Object, ByVal contactName As String) Handles oneAddForm.addSuccess
    statusLabel.Text = contactName & " has been added to your contact list."
End Sub
//...and to put in the event handler

但是,当尝试在关闭一个表单后再次加载oneAddForm表单时,会导致“无法访问已释放的对象…”异常。


-1

我想提供一个稍微不同的答案,对我非常有效。

上面的回答中的以下代码对我非常有效,只要我没有在MDI父窗体中进行任何代码更改。当我插入类似于 form1.MDIparent=me 的代码时,一切都失败了。因此,我省略了这一步。

下面的Form1需要是您正在使用的MDI父窗体的名称。然后,在我的环境中,它可以很好地用于传递给父级变量或访问父级的其他功能。

在这之前,我遇到了一个问题,即子项调用所有空白字段的不同父项!

CType(Me.ParentForm, Form1).control1.Text = "Title bar text"
'Status Strip Label
CType(Me.ParentForm, Form1).StatusLabel.Text = "Status Strip Text"

CType(Me.parentForm, Form1).variableDefinedinParentString = "abc" 'passing a variable

CType(Me.parentForm, Form1).subroutineLOCATEDinPARENT() 'Calling a subroutine in the parent

也许这会对其他人有所帮助。我希望如此!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接