How to pass a form, object or data to a second for

2020-01-29 22:25发布

I have created 2 forms. The first one is the button that you want to back up. In the second there are paths that can be modified. How to make a reference that after pressing the "backup" button will get a path of 2 forms. The path is saved when I closed form2 I know how to do it in one form but unfortunately I can not refer to another form.

Source of Form 2:

Private Sub Browser_from1_Click(sender As Object, e As EventArgs) Handles Browser_from1.Click
        Dim FolderBrowserDialog1 As New FolderBrowserDialog
        FolderBrowserDialog1.ShowDialog()
        TextBox1from.Text = FolderBrowserDialog1.SelectedPath

        If Browser_from1.Text <> "" And TextBox1from.Text <> "" Then
            Backup.StartCopy.Enabled = True

        End If

    End Sub

    Private Sub Browser_to1_Click(sender As Object, e As EventArgs) Handles Browser_to1.Click
        Dim FolderBrowserDialog1 As New FolderBrowserDialog
        FolderBrowserDialog1.ShowDialog()
        TextBox2to.Text = FolderBrowserDialog1.SelectedPath

        If Browser_to1.Text <> "" And TextBox2to.Text <> "" Then
            Backup.StartCopy.Enabled = True

        End If
    End Sub

    Private Sub TextBox1from_TextChanged(sender As Object, e As EventArgs) Handles TextBox1from.TextChanged

    End Sub

    Private Sub save_settings_Click(sender As Object, e As EventArgs) Handles save_settings.Click
        My.Settings.pathmem = TextBox2to.Text
        My.Settings.pathmem1 = TextBox1from.Text
        My.Settings.Save()
    End Sub

    Private Sub setting_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TextBox1from.Text = My.Settings.pathmem1
        TextBox2to.Text = My.Settings.pathmem
    End Sub
End Class

2条回答
何必那么认真
2楼-- · 2020-01-29 22:35

You dont want to create a reference to a form - that would (or could) create a whole new form. You want to hold onto the form reference.

This is done by passing a reference to the forms, but the talk of one form fiddling with the controls on another form is a bad idea because it breaks encapsulation. But forms are classes (it says so at the top of each one), so you can add Properties and Methods (Sub and/or Functions) to facilitate passing information back and forth.

Method One - Passing a Form Reference

The simplest way is to pass whatever the other form needs in the constructor:

' form 1 / "main" form / form to return to

Dim frm As New Form6(Me)

frm.Show()
Me.Hide()

In order for this to work, you need to modify the constructor (Sub New) on the destination form:

Private frmReturnTo As Form
Public Sub New(f As Form)
    ' This call is required by the designer.
    InitializeComponent()

    frmReturnTo = f

End Sub

It is best not to create your own constructor until you are familiar with them. Use the drop downs at the top of the code window: from the left pick the form name; from the right, select New. The designer adds required code to them which must not be changed.

enter image description here

Do not add any code before the InitializeComponent() call at least until you are familiar with the life cycle of a form. The form and its controls do not exist until that runs.

To return to the "main" form:

If frmReturnTo IsNot Nothing Then
    frmReturnTo.Show()
End If

You may want to remove some of the title bar buttons or add code to the form Closing event to handle when the user closes via the system menu or buttons.

Using the constructor is ideal for cases where there is some bit of data which the form must have in order to do its job.

Method Two - Passing Data

Thats all well and good, but what about passing data to another form? You can use the constructor for that too. In order to pass say, a string, integer and a Point:

' destination / second form:
Public Sub New(a As String, b As Int32, c As Point)
    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Label1.Text = a
    Label2.Text = b.ToString
    Label3.Text = c.ToString

End Sub

Call it like this:

' method two: pass data you want to share in the ctor
Dim frm As New frmData("hello", 6, New Point(150, 550))

frm.Show()

Result:

enter image description here

Method Three: Properties

Thats fine, but if there is a lots of data that way can get cumbersome. Plus, you may want to update some of the data from the calling/main form. For this you can create Properties on the form to handle the data:

Public Property Label1Text As String
    Get
        Return Me.Label1.Text
    End Get
    Set(value As String)
        Me.Label1.Text = value
    End Set
End Property

Rather than a private variable to act as the backing field, one of the controls is used. The name leaves a bit to be desired as it exposes implementation details. So, use names which describe what the data represents rather than where it displays.

Public Property SpecialValue As Integer
    Get
        Return Integer.Parse(Me.Label2.Text)
    End Get
    Set(value As Integer)
        Me.Label2.Text = value.ToString
    End Set
End Property

Public Property SomePoint As Point
    Get
        Dim data = Me.Label3.Text.Split(","c)
        Return New Point(Convert.ToInt32(data(0)),
                         Convert.ToInt32(data(1))
                        )
    End Get
    Set(value As Point)
        Me.Label3.Text = value.X.ToString & "," & value.Y.ToString
    End Set
End Property

A point was used just to show that other data types can be used. Setting those values from the calling/original/source form:

Using frm As New Form6
    frm.Label1Text = "Ziggy"
    frm.SpecialValue = 42
    frm.SomePoint = New Point(111, 222)

    frm.ShowDialog()

    ' do stuff here with any changes
    Dim theint = frm.SpecialValue

End Using          ' dispose of dialog

The destination controls would well have been TextBoxes for the user to edit. The Property "wrappers" allow you to fetch those values back, so in this case, a Dialog was used.

Method Four: Methods

You can also use methods as a way to pass data to the second/helper form. Here a List(of T) collection will be passed. In the child/display form a method is added to receive the data which it then displays. The task represented is proofing or viewing a filtered list:

Public Sub UpdateDisplay(lst As List(Of SimpleItem), filter As String)
    DataGridView1.DataSource = lst
    Label1.Text = String.Format("{0} Total {1} Items", lst.Count, filter)
End Sub

In the main/calling form:

' form level variable
Private frmDV As frmDataView

elsewhere...perhaps in a Click event:

' myList is a simple list of items
' Users pick which color to filter on via a combo box

Dim filter As String
If cboListFilter.SelectedItem IsNot Nothing Then
    'Dim frmDV As New frmDataView
    If frmDV Is Nothing OrElse frmDV.IsDisposed Then
        frmDV = New frmDataView
    End If

    filter = cboListFilter.SelectedItem.ToString()
    ' apply the filter
    Dim tmpList = myList.Where(Function(w) w.Color = filter).ToList()
    frmDV.UpdateDisplay(tmpList, filter)

    frmDV.Show()
Else
    Return

End If

Result:

enter image description here

With DataBased apps a modified version of this can allow for the case where you display DataGridView data in detail form on another form. You need not have the second form rung SQL to add or update the record, and then the main form running another query to "refresh" the display. If the DataSource is a DataTable backed up by a fully configured DataAdapter, pass the DataTable and have the child form add, change or delete using that. The data will automagically be in the DataTable andDataGridView`.


There are other ways to do this, but they generally all boil down to passing something from A to B. Which way is "best" depends on what the app does, the use-case and the nature of the data. There is no one right way or best way.

For instance, Properties and in many cases Functions allow the B Form to close the feedback loop. With DB items, a DataChanged property might tell the calling form that data was added or changed so that form knows to use the DataAdapter to update the db.

查看更多
▲ chillily
3楼-- · 2020-01-29 22:51
'SECOND FORM

Public class secondForm (blah blah)
Public overloads property owner as myMainForm
'Must be only the form you prepared for that 

Private sub secondForm_load(blah blah) handles blah blah
Texbox1.text=Owner.customcontrol.text
End sub

End class

'MAIN FORM

public class myMainForm(blah blah)

Private sub button1_click(blah blah) handles blah blah

Dim NewSecondForm as secondForm = New secondForm
NewSecondForm.owner(me)
NewSecondForm.show(me)
NewSecondForm.dispose()

' so you can have bidirectional communication between the two forms and access all the controls and properties from each other
End sub
End Class
查看更多
登录 后发表回答