表单传递数据_如何在.NET中的表单之间传递数据

表单传递数据

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .NET novice.

这似乎很简单,但是我看到重复的问题问如何做:如何在两种形式之间传递数据。 在本文中,我将向您展示实现这一目标的不同机制。 本文针对.NET新手。

The first thing you should realize about Form in .NET is that they are classes. How do you or I know that they are classes? The code tells you:

关于.NET中的Form,您应该意识到的第一件事是它们是类。 您或我怎么知道它们是课程? 该代码告诉您:

C#

C#

public partial class Form1 : Form

VB

VB

Public Class Form1

Take note of the "class" keyword. This is your indicator that forms are classes. "Ok, fine. Forms are classes. So what?" Well, if you think of forms as classes, which they are, then you can begin to realize how to share data between forms. How do you share data between two classes? You create references to two different instances and then share data via each class' public members. The same holds true for forms. You can create public members (or parameterized constructors or static members) to accept external data. Where I think most people get tripped up by this concept is the the scope each reference has.

注意“ class”关键字。 这是形式是类的指标。 “好吧,好的。表格就是类。那又如何呢?” 好吧,如果您将表单视为类,那么它们可以开始意识到如何在表单之间共享数据。 您如何在两个班级之间共享数据? 您创建对两个不同实例的引用,然后通过每个类的公共成员共享数据。 表单也是如此。 您可以创建公共成员(或参数化构造函数或静态成员)以接受外部数据。 我认为大多数人都会被这个概念所绊倒,这是每个参考文献所具有的范围。

可变范围 (Variable Scope)

What is "scope?" Scope deals with what parts of code a variable is visible (accessible) to. There are typically two types of scope:  global and local. Global scope can mean a variable is accessible to all parts of class, file, or assembly, depending on how you modify the variable's declaration. Local scope usually means a variable that can only be accessed from within the same function or block--blocks are things like for and while loops, if statements, etc. You can think of blocks as anything between curly braces in C# or anything between an opening statement and its matching "End" statement in VB (If/End If for example).

什么是“范围”? 范围处理变量对代码的哪些部分可见(可访问)。 通常有两种类型的范围:全局和局部。 全局范围可能意味着该变量可用于类,文件或程序集的所有部分,具体取决于您如何修改变量的声明。 局部作用域通常表示只能从同一函数或块中访问的变量-块是forwhile循环, if语句之类东西。您可以将块视为C#中花括号之间的任何内容或VB中的open语句及其匹配的“ End”语句(例如,If / End If)。

Why is scope relevant to passing data between forms? You are going to need to pay attention to how your instances are scoped in order to be able to effectively pass data between forms. Let's look at an example of variable scope.

为什么范围与在表单之间传递数据有关? 您将需要注意实例的范围,以便能够在表单之间有效地传递数据。 让我们看一个变量范围的例子。

C#

C#

public partial class Form1 : Form
{
    private Form2 f2 = new Form2();

    public void MyArbitraryMethod1()
    {
        Form2 f3 = new Form2();

        // I CAN ACCESS f2 AND f3
    }

    public void MyArbitraryMethod2()
    {
        // I CAN ACCESS f2
    }
}

VB

VB

Public Class Form1
    Private f2 As New Form2()

    Public Sub MyArbitraryMethod1()
        Dim f3 As New Form2()

        ' I CAN ACCESS f2 AND f3
    End Sub

    Public Sub MyArbitraryMethod2()
        ' I CAN ACCESS f2
    End Sub
End Class

In the above code samples, f2 has global scope to the class because it is declared at the class level (basically, outside of any function). It can be accessed by any method within the class. f3 has local scope to the function MyArbitraryMethod1 because it is declared at the function level. It can only be accessed within MyArbitraryMethod1. One thing that is not demonstrated above, but that you should be aware of is that f2 and f3 internally cannot access any data from the Form1. We'll see a bit later how to provide this access.

在上面的代码示例中, f2具有类的全局作用域,因为它是在类级别(基本上在任何函数之外)声明的。 该类中的任何方法都可以访问它。 f3具有MyArbitraryMethod1函数的局部作用域,因为它是在函数级别声明的。 只能在MyArbitraryMethod1中访问 。 上面没有演示的一件事,但您应该注意的是, f2f3在内部无法访问Form1中的任何数据。 稍后我们将看到如何提供此访问权限。

Here's a breakdown of how you could share data given our current example. Since MyArbitraryMethod1 can access both f2 and f3, you could share data between those two forms. In contrast, within function MyArbitraryMethod2 you could not share data between the two forms since within that function, f3 does not exist. In order to share data between the two forms within the MyArbitraryMethod2 method, you would have to widen the scope of f3. "Widening the scope" of a variable just means to increase the areas of code which can access a variable. For this simple example, the only widening route you have is to change f3 from a local variable to a global variable. Had f3 been declared from within an if statement, then f3 would have been accessible only from within the if. In widening its scope, you could either relocate f3 to be local to the function (rather than local to the if block) or you could relocate f3 to be global to the class.

这是在当前示例下如何共享数据的细分。 由于MyArbitraryMethod1可以访问f2f3 ,因此可以在这两种形式之间共享数据。 相反,在函数MyArbitraryMethod2中,您无法在两种形式之间共享数据,因为在该函数中, f3不存在。 为了在MyArbitraryMethod2方法内的两种形式之间共享数据,您必须f3的范围。 “拓宽变量的范围”仅意味着增加可以访问变量的代码区域。 对于这个简单的示例,唯一的扩展途径是将f3从局部变量更改为全局变量。 从if语句中有F3已经声明,那么F3本来访问仅从如果内。 为了扩大其范围,您可以将f3重新定位为函数的本地变量(而不是if块的局部变量),也可以将f3定位为全局类。

You may have noticed that I didn't mention Form1, the class in which we are writing this code, in the above example. That's because I saved it for this paragraph! Since we are working from within Form1, we can share data between any form we declare from within Form1's code--from anywhere in the code as long as the form object we are sharing data with is in scope. This means the same thing as I described above with regard to declaration of f3. If we are not working in a function which has access to a different form object, then we cannot share data. For our previous example, in MyArbitraryMethod1, we can share data between Form1 objects and f2 or f3, but in MyArbitraryMethod2, we can only share data with f2.

您可能已经注意到,在上面的示例中,我没有提到Form1 ,即我们在其中编写此代码的类。 那是因为我将其保存在本段中! 由于我们是在Form1内进行工作的,因此我们可以在Form1的代码中声明的任何表单之间共享数据-可以在代码中的任何位置共享数据,只要我们与之共享数据的表单对象在范围之内即可。 这意味着与我上面关于f3声明所描述的相同。 如果我们不使用可以访问其他表单对象的函数,则无法共享数据。 对于前面的示例,在MyArbitraryMethod1中 ,我们可以在Form1对象与f2f3之间共享数据,但是在MyArbitraryMethod2中 ,我们只能与f2共享数据。

分享方式 (How to Share)

因此,我们研究了 when we can share data, but we still haven't covered how. Here's how. I mentioned previously that you can share data by means of public or static members, or by passing data to constructors. Let's take a look at each method.

Public Methods and Constructors

公共方法和构造函数

I'm including these as one in the same because you could think of a constructor as being a method--at least with respect to what we're doing here. Let's expand our previous example:

我将它们作为一个整体包含在内,因为您可以将构造函数视为一种方法,至少就我们在此处所做的而言。 让我们扩展前面的示例:

C#

C#

public partial class Form2 : Form
{
    private string _form1Data;

    public Form2(string form1Data)
    {
        InitializeComponent();

        this._form1Data = form1Data;
    }

    public void SomeFunction1()
    {

    }

    public void SomeFunction2(string form1Data)
    {

    }
}

VB

VB

Public Class Form2
    Private _form1Data As String

    Public Sub New(ByVal form1Data As String)
        InitializeComponent()

        Me._form1Data = form1Data
    End Sub

    Public Sub SomeFunction1()

    End Sub

    Public Sub SomeFunction2(ByVal form1Data As String)

    End Sub
End Class

Here, we are looking at Form2's code now. I have included both an example of passing via the constructor and passing via a method. The difference I'd like to make note of is that  we took in Form1 data as a parameter in the constructor. We then saved this data to a private variable within Form2. This private variable has global scope to Form2's code. Both SomeFunction1 and SomeFunction2 could subsequently access this value. There is nothing saying we must save the incoming Form1 data to a private variable. Perhaps you want to perform some calculation on the incoming data and store the result in some other member or field of Form2. This is perfectly fine. For this example, just know that if you pass data via a constructor and you want that data to be accessible to other parts of the class, then you will have to save the data somewhere--here I used the private member variable _form1Data. Now onto the methods.

在这里,我们现在在看Form2的代码。 我已经提供了通过构造函数传递和通过方法传递的示例。 我要指出的区别是,我们将Form1数据作为构造函数中的参数。 然后,我们将该数据保存到Form2中的私有变量中。 此私有变量具有Form2的代码的SomeFunction1SomeFunction2随后都可以访问该值。 没什么好说的,我们Form1数据保存到私有变量中。 也许您想对传入的数据执行一些计算,并将结果存储在Form2的其他成员或字段中。 很好 对于此示例,只知道如果您通过构造函数传递数据,并且希望该数据可被类的其他部分访问,那么您将不得不将数据保存在某处,这里我使用了私有成员变量_form1Data 。 现在介绍方法。

For SomeFunction1 and SomeFunction2, scope rules are still in effect (and they always will be). SomeFunction1 has no knowledge of the parameter which SomeFunction2 takes. It can have knowledge of it if you save this data to some member variable, but this is a "dumb" knowledge. SomeFunction1 doesn't really know that SomeFunction2 takes a parameter; it just knows that some member variable can be accessed by it, due to scoping. It would be up to SomeFunction2 to assign the incoming Form1 data to the private member variable of the class.

对于SomeFunction1SomeFunction2 ,作用域规则仍然有效(并且将始终有效)。 SomeFunction1没有哪个SomeFunction2带有参数的知识。 如果将数据保存到某个成员变量中,它可能具有相关知识,但这是一个“愚蠢”的知识。 SomeFunction1并不真正知道SomeFunction2需要一个参数。 它只是知道,由于作用域,它可以访问某些成员变量。 将传入的Form1数据分配给该类的私有成员变量取决于SomeFunction2

If we have this mechanism to pass data, how do execute it from the other form? Well, since these mechanisms we have created are public members, they can be called from our other form provided we have valid instances. Here's what that could look like:

如果我们有此机制来传递数据,如何从其他形式执行数据呢? 好吧,由于我们创建的这些机制是公共成员,因此只要我们有有效的实例,就可以从其他表格中调用它们。 可能是这样的:

C#

C#

public partial class Form1 : Form
{
    private string _dataToPass = "Hello World!";

    public void MyArbitraryMethod1()
    {
        Form2 f3 = new Form2();

        f3.SomeFunction2(this._dataToPass);
        f3.Show();
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
        MyArbitraryMethod1();
    }
}

VB

VB

Public Class Form1
    Private _dataToPass As String = "Hello World!"

    Public Sub MyArbitraryMethod1()
        Dim f3 As New Form2()

        f3.SomeFunction2(Me._dataToPass)
        f3.Show()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MyArbitraryMethod1()
    End Sub
End Class

In MyArbitraryMethod1, we have created a new instance of a Form2 class. Take note that we are passing a string that is private to the Form1 class. This string does not exist in Form2's code, at the moment. We use one of the public data-passing mechanisms we just covered to share the data, namely passing via a function. In Form2, we can now work with the Form1 data.

MyArbitraryMethod1中 ,我们创建了一个Form2类的新实例。 请注意,我们传递了一个对Form1类私有的字符串。 目前,该字符串在Form2的代码中不存在。 我们使用刚刚介绍的一种公共数据传递机制来共享数据,即通过一个函数传递。 在Form2中 ,我们现在可以使用Form1数据。

C#

C#

public void SomeFunction2(string form1Data)
{
    this.label1.Text = form1Data;
}

VB

VB

Public Sub SomeFunction2(ByVal form1Data As String)
    Me.Label1.Text = form1Data
End Sub

One technicality to be aware of here is that for this demonstration we are passing a string. string in .NET is a reference type, but it behaves like a value type. What does that mean? Well, in Form2, we are working with a copy of the string we passed in from Form1. There are ways to overcome this and actually work with the string declared on Form1. Adding the ref or out keywords in C# and changing the ByVal to ByRef in VB would accomplish this. The point here is that you should be careful with your references when passing data between forms (or any class for that matter) and know whether you are working with a copy of the data or the actual data.

这里要注意的一种技术是,在此演示中,我们传递了一个字符串 。 .NET中的string是引用类型,但其行为类似于值类型。 那是什么意思? 好,在Form2中,我们正在处理从Form1传入的字符串的refout关键字,然后在VB中将ByVal更改为ByRef即可完成此操作。 这里的要点是,在表单(或与此相关的任何类)之间传递数据时,应谨慎使用引用,并知道要使用数据的副本还是实际的数据。

Here is the output you would receive with the above code:

这是使用上面的代码将收到的输出:

Data Passed to Form2

Note that the string "Hello World!" doesn't occur anywhere in Form2's code--we passed it in from Form1. Yes, it's that simple!

请注意,字符串“ Hello World!” 在Form2的代码中不会出现-我们是从Form1传递过来的。 是的,就是这么简单!

Public Properties

公共财产

Behind the scenes, properties in .NET are turned into getter and setter methods. Since the syntax is a bit different from a method, however, I thought I'd have a separate section on properties.

在后台,.NET中的属性变成了getter和setter方法。 由于语法与方法略有不同,因此,我认为我将在属性上有单独的部分。

Even though I'm giving you a separate section on properties, in actuality there is not much different in the way you pass data. The only real difference is that instead of making a function call and either immediately working with the value or storing the value for later use, you store the value immediately for later use. Here's an example:

即使我为您提供了关于属性的单独部分,实际上,您传递数据的方式也没有太大不同。 唯一的真正区别是,您无需立即进行功能调用或立即使用该值或将该值存储以供以后使用,而是立即存储该值以供以后使用。 这是一个例子:

C#

C#

Property Definition

属性定义

using System.Windows.Forms;

namespace WindowsFormsApplication13
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public string StringToDisplay
        {
            get { return this.label1.Text; }
            set { this.label1.Text = value; }
        }
    }
}

Sharing Via the Property

通过财产分享

using System.Windows.Forms;

namespace WindowsFormsApplication13
{
    public partial class Form1 : Form
    {
        private string _dataToPass = "Hello World!";

        public void MyArbitraryMethod1()
        {
            Form2 f3 = new Form2();

            f3.StringToDisplay = this._dataToPass;
            f3.Show();
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            MyArbitraryMethod1();
        }
    }
}

VB

VB

Property Definition

属性定义

Public Class Form2
    Public Sub New()
        InitializeComponent()
    End Sub

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

Sharing Via the Property

通过财产分享

Public Class Form1
    Private _dataToPass As String = "Hello World!"

    Public Sub MyArbitraryMethod1()
        Dim f3 As New Form2()

        f3.StringToDisplay = Me._dataToPass
        f3.Show()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.MyArbitraryMethod1()
    End Sub
End Class

The result is the same as that displayed in the above image.

结果与上图中显示的结果相同。

Passing a Reference to the Parent Form

传递对父表格的引用

Similar to passing data via functions or properties, another way to access data from one form on another would be to pass a reference to the "parent" form itself. In reality, this is the same thing as what we saw in Public Methods and Constructors. The benefit to this approach is that you open up access to all public members of the parent form from within the child form, rather than just a fixed number of data elements. Setting up this approach is simple: do the same thing we saw in Public Methods and Constructors, except that instead of passing a data element of type string (in the above example), change your procedure to accept an element of the type which the parent form is. Here's an example.

与通过函数或属性传递数据相似,从另一表单访问数据的另一种方法是将引用传递给“父”表单本身。 实际上,这与我们在字符串类型的数据元素(在上面的示例中),而是将过程更改为接受父类型的元素形式是。 这是一个例子。

C#

C#

Passing the Reference

通过参考

public partial class Form1 : Form
{
    private string _dataToPass = "Hello World!";

    public void MyArbitraryMethod1()
    {
        Form2 f3 = new Form2(this);

        f3.Show();
    }

    public string StringToDisplay
    {
        get { return this._dataToPass; }
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
        MyArbitraryMethod1();
    }
}

Sharing Via the Form Reference

通过表单参考共享

public partial class Form2 : Form
{
    public Form2(Form1 form1Instance)
    {
        InitializeComponent();

        this.label1.Text = form1Instance.StringToDisplay;
    }
}

VB

VB

Passing the Reference

通过参考

Public Class Form1
    Private _dataToPass As String = "Hello World!"

    Public Sub MyArbitraryMethod1()
        Dim f3 As New Form2(Me)

        f3.Show()
    End Sub

    Public ReadOnly Property StringToDisplay() As String
        Get
            Return Me._dataToPass
        End Get
    End Property

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MyArbitraryMethod1()
    End Sub
End Class

Sharing Via the Form Reference

通过表单参考共享

Public Class Form2
    Public Sub New(ByRef form1Instance As Form1)
        InitializeComponent()

        Me.Label1.Text = form1Instance.StringToDisplay
    End Sub
End Class

Notice that we pass a Form1 reference to Form2 by way of the this (Me in VB) keyword. Because Form2 now has a reference to a valid instance of a Form1 object, Form2 has access to Form1's public members, including fields, properties, and methods.

请注意,我们通过this (在VB中为Me )关键字将Form1引用传递给Form2 。 因为现在Form2引用了Form1对象的有效实例,所以Form2可以访问Form1的公共成员,包括字段,属性和方法。

Static Members

静态成员

This could be considered an extension to the previous two methods (excluding constructors), but it is different enough to warrant its own section. Static ("shared" in VB) members are those that do not need a valid instance in order to be referenced. If you have ever called MessageBox.Show(), then you have used a static member. Think about it. Did you have to create a new MessageBox object in order to call Show(), or did you just call it? Any time you call a method, assign to or read from a property, or assign directly to certain variables by using the syntax

这可以被认为是对前两种方法的扩展(不包括构造函数),但足以保证其自己的部分。 静态(在VB中为“共享”)成员是不需要有效实例才能被引用的成员。 如果您曾经调用过MessageBox.Show() ,那么您已经使用了静态成员。 想一想。 您是否必须创建一个新的MessageBox对象才能调用Show() ,还是只是调用它? 任何时候调用方法,分配给属性或从属性中读取或通过使用语法直接分配给某些变量

[ClassName].[MemberName] [ClassName]。[MemberName]

you are referring to static members. This access convention is why it's a bad idea to give properties the same name as their encasing class.

您指的是静态成员。 使用此访问约定的原因是,给属性赋予与其封装类相同的名称是个坏主意。

The thing to be aware of when dealing with static members is that only one occurrence of the member exists for every instance of a particular class. I'll discuss this while we examine our next example.

处理静态成员时要注意的是, 对于特定类的每个实例仅存在一次该成员 。 我将在讨论下一个示例时对此进行讨论。

C#

C#

Creating the Second Form

创建第二种形式

public partial class Form1 : Form
{
    public static string _dataToPass = "Hello World!";

    public void MyArbitraryMethod1()
    {
        Form2 f3 = new Form2();

        f3.Show();
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
        MyArbitraryMethod1();
    }
}

Sharing Via the Static Member

通过静态成员共享

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();

        this.label1.Text = Form1._dataToPass;
    }
}

VB

VB

Creating the Second Form

创建第二种形式

Public Class Form1
    Public Shared _dataToPass As String = "Hello World!"

    Public Sub MyArbitraryMethod1()
        Dim f3 As New Form2()

        f3.Show()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MyArbitraryMethod1()
    End Sub
End Class

Sharing Via the Static Member

通过静态成员共享

Public Class Form2
    Public Sub New()
        InitializeComponent()

        Me.Label1.Text = Form1._dataToPass
    End Sub
End Class

Have you noticed the difference here? Whereas in the last two examples Form1's data was pushed to Form2 from directly within Form1, here we are pulling the data from Form1 from within Form2. This is due to the nature of static members and how you access them via the class name rather than an instance name. Now is probably a good time as any to talk about the negative of this approach:

您注意到这里的区别了吗? 而在最后两个例子Form1中的数据中Form1的直接推到窗体2,在这里我们从内部拉窗体2Form1数据。 这是由于静态成员的性质以及如何通过类名称而不是实例名称访问它们。 现在可能是讨论这种方法的负面影响的好时机:

It is generally a bad idea to use static (shared) members to share data between two instances. Any time you change a static value, every instance of the class will see this change. It is very easy to introduce bugs via this mechanism and it should be used judiciously.

The result of the above code is the same as the image above.

上面代码的结果与上面的图片相同。

摘要 (Summary)

Congratulations if you've made it this far. I realize there was quite a bit of reading to get to this point. You should have a decent understanding of what mechanisms exist for you to share data among your forms. Keep in mind that you can share public data between forms provided there is some scope relationship between the forms--meaning one form is accessible to the other (or both forms are accessible to each other). You can also share data by implementing static members. Static members will be shared between all instances of the class, so a change to a static member in one instance will be seen by all instances. Another caveat of static members is that even private static members will be shared among instances--they just won't be accessible by objects of a different type. In the grand scheme of things, just remember that .NET treats forms as classes, and that you share data between forms the way you share data between any class. Don't sweat it if you get tripped up on your initial attempts at implementing these concepts in your code--you can always come to EE to share your frustrations!

如果您已经做到了,那么恭喜您。 我意识到有很多阅读可以达到这一点。 您应该对存在哪些机制可以在表单之间共享数据有一个不错的了解。 请记住,只要表单之间存在某种范围关系,就可以在表单之间共享公共数据-意味着一个表单可以被另一表单访问(或者两种表单可以彼此访问)。 您还可以通过实现静态成员来共享数据。 静态成员将在该类的所有实例之间共享,因此

翻译自: https://www.experts-exchange.com/articles/4322/How-to-Pass-Data-Between-Forms-in-NET.html

表单传递数据

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值