在其他Windows窗体类中访问变量

3

如果有人能帮我解决这个问题,我将不胜感激。

我有一个Windows窗体应用程序,它包含三个窗体:form1、form2和form3。当应用程序被激活时,form1会启动。在form1上,有一个按钮可以打开form2并隐藏form1。在form2上也有一个按钮,可以打开form3并隐藏form2。

public partial class Form1 : Form
{

    Form2 f2= new Form2();
    public Form1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        this.Hide();            
        f2.Show();        
    }
}


public partial class Form2 : Form
{
            Form3 f3 = new Form3();
    private void button1_Click(object sender, EventArgs e)
    {
         this.Hide();
         f3.Show();                
    }
 }

问题在于form3中,我试图访问在运行时在form2中分配值的某些变量。我认为由于我将f2设置为无模式窗体,所以只需使用f2.myvariables就可以访问,但智能提示没有给出f2对象。为什么会这样?我找到了一种方法来声明那些变量为public static,所以我可以通过使用form2.myvariables来访问...这里有另一件让我困惑的事情。既然所有的值都是在运行时分配的,那么静态变量怎么能做到这一点呢?我是C#的新手,我已经做了很多关于此方面的搜索,但似乎没有地方确切地回答我的问题。提前感谢你的帮助!

我不知道如何修复糟糕的格式...抱歉..我是新手。 - John
2
可能是重复的问题:http://stackoverflow.com/questions/2155050 - Uwe Keim
这些是编程基础知识,稍微广泛了一点,很难在SO帖子中回答(IHMO)。 - CodingGorilla
你的表单类可能位于不同的命名空间中。为了使智能感知能够访问这些属性,你需要在类顶部添加一个带有这些命名空间的 'using' 语句。 - Belmiris
当你将表单视为与类不同的东西时,所有这些混淆都开始了。表单是一个类。想想如何访问另一个类的变量。 - Anirudha
这个问题已经关闭了,但是答案很可能会帮助我解决当前的问题。 - ptay
4个回答

11

所以您在父表单(form2)中有信息,希望在子表单(form3)的方法中访问它。

  1. form3中创建需要的信息属性。
  2. form2创建form3的实例时,应设置这些属性。

您应该把这个过程看作是父表单向其子表单提供信息,而不是子表单从其父表单请求信息。如果您能相应地调整自己的思维方式,那么代码不仅更容易编写,而且还符合良好的编码实践(较低的耦合度,不会在外部暴露更多的信息等)。

要创建一个属性,在form3中可以像这样做:

//TODO: give real name; adjust type as needed
public string SomePropertyName { get; set; }

然后在form2中你可以这样做:

f3.SomePropertyName = "hello from form2";
或者
f3.SomePropertyName = someVariableInForm2;

嗨Servy,谢谢你的帖子。我不知道如何使用属性来解决这个问题?就像在form3中声明构造函数一样,当在form2中创建form3的实例时,通过构造函数传递所有变量? - John
@John 这绝对是一个非常有效的替代方案,几乎与此解决方案完全相同。我将进行编辑以显示创建属性的语法。 - Servy
非常感谢。您能告诉我为什么在f3中无法访问f2实例吗?是因为子窗体无法访问父窗体吗?另外,为什么将这些变量设为public static也可以解决此问题?我的意思是这些变量被赋予基于用户运行时输入的值。根据我的理解,public static只适用于在运行时不会更改的值。对于提出这么多问题,非常抱歉。我只是想了解整个过程而不仅仅是解决问题。 - John
@John 在你的原始代码中,f2 是一个私有实例变量,这意味着它只能被非静态方法在该类内部访问。如果你将其设置为公共的(虽然不应该这样做,因为使用公共实例变量被认为是不好的编程习惯),那么如果你有 Form1 的实例(它是具有 f2 变量的类),你就可以访问它了。现在的问题是你没有 Form1 的实例,所以你仍然无法访问它。如果 f2 是静态的,那么你不需要 Form1 的实例来访问它的字段,你只需要使用类名即可。 - Servy
正如我在其他地方所说的,你不想这样做。这些表单变量应该是非静态和私有的。你应该在Form3上使用公共属性或在构造函数中使用参数来传递值,而不是使它们成为静态的或更多地暴露各种表单变量。 - Servy

1

嘿,

试着创建Form3的构造方法的过载,将来自form2的变量值作为方法参数传递。


谢谢。我想这应该可以解决问题,但为什么父窗体(f2)实例在子窗体(f3)实例中无法访问呢? - John
@John,因为它超出了范围。如果您在两个表单对象之间建立链接,那么它将起作用,只需在Form3中创建一个类型为Form的父属性,并在调用Form3的构造函数时将该属性分配给form2 form3.Parent = form2 - Rodrigo Reis
请注意,执行Rodrigo建议的操作通常被认为是一种不好的实践。就像将所有内容都变成“静态”,这涉及公开更多不应该公开的信息。 - Servy
好的,@Servy,请您回答这个问题。 - Rodrigo Reis
@RodrigoReis,我指的是传递父表单引用的评论,这在我看来只是糟糕的代码味道,而不是你答案的内容(这是一个很好的解决方案+1)。哦,顺便说一下,我之前回答过这个问题。 - Servy
微软文档做同样的事情,请参阅@ ContainerControl.ParentForm Property - Rodrigo Reis

0
如果您已经在Form2上将相关变量设置为public,则问题在于您还将它们设置为static。当您将它们定义为static时,您是将它们放置在类型(Form2)上而不是实例(f2)上。
从变量声明中删除static,它们应该会出现在f2的智能感知中。

根据@Uwe Keim上面分享的链接,我强烈建议将它们变成公共属性,而不是公共变量。 - Brian S
问题出在Form3中,无论静态变量是否被移除,Intellisense中都找不到f2。 - John

0
我认为,由于我将f2设置为无模式窗体,所以我应该能够通过简单地使用f2.myvariables来访问它,但是智能感知没有给我f2对象。为什么会这样呢?
一旦您创建了类的实例,所有声明为public的变量和方法都应该可用。请再次检查您是否将变量声明为public。
所有的值都是在运行时分配的,静态变量怎么做到的呢?
不,静态变量和方法是在程序启动时定义的。它们不需要创建实例来引用它们。

所有的东西都以public为前缀,我知道静态变量可以在不创建类对象的情况下使用,但我的困惑是,form2上的变量值不能预先确定,而是根据用户在form2上的输入进行分配;然而,在这种情况下,将这些变量设置为静态确实解决了问题...为什么? - John
@John 把所有东西都设为 public static 只会让所有变量变成全局变量。在这种情况下,你并不真的想要这样做;每个表单都应该有一个变量的副本。它之所以能够工作,是因为只有一个表单。虽然在简单的情况下它确实可以工作,但这不是好的实践,而且基本上会成为你学习如何正确做事的绊脚石。 - Servy

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