【问题标题】:Passing Data back to First Form from Second Form in C#在 C# 中将数据从第二种形式传递回第一种形式
【发布时间】:2011-07-20 10:17:55
【问题描述】:

我有两个表格。说FormAFormB

我从 FormA 调用 FormB 使用 frmB.Show();

在 FormB 中,我有两个文本框和一个组合框控件。 假设用户在这两个文本框中输入了一些数据,并从 Form2 的组合框中选择了一个项目,然后单击了 OK 按钮。

点击后我想要那些文本框用户输入的值,组合框选择的项目值回到FormA

我如何使用 C# 来实现这一点。

【问题讨论】:

  • 你能检查你的标签吗?这真的是一个 c#-4 特定的问题吗?另外,您的表格是 WinForms 吗?谢谢
  • 是的。如果 4.0 中有更好的解决方案,那就太好了。
  • 如何让控件(运行执行点)从 FormB 回到 FormA。
  • 您是否尝试使用 ShowDialog() 打开表单。即使在它被赞成之后,你也忽略了这个答案。如果您能提供您认为此解决方案不足的原因,将会很有帮助。

标签: c# c#-4.0


【解决方案1】:

一个肮脏但也是最快的解决方案是将这些控制公开。您可以通过在 Form2.Decisgner.cs 文件中添加单词 public 来做到这一点。如果 FormA 有 FormB 的成员变量或局部变量,您可以通过以下方式访问控件(例如 TextBox1):

frmB.TextBox1.Text

现在也可以在 FormB 之外访问。

【讨论】:

  • 不符合您的简单陈述。请用代码正确地告诉我。
  • 您使用的是 .NET C# 表单吗?每个表单至少包含两个文件,假设您的 FormB 在文件 FormB.cs 和 FormB.Designer.CS 中定义。并假设您的文本框称为 TextBox1 和 TextBox2。在 FormB.Designer.cs 文件中检查“private System.Windows.Forms.TextBox textBox1;”或模拟。将工作“私人”替换为“公共”。现在,无论您说“frmB.Show()”,您也可以说“frmB.textBox1.Text”,这将在该点返回文本框中的文本。例如,你可以说'string myText = frmB.textBox1.Text'。
【解决方案2】:

如果它在同一页面上,您应该可以直接从控件中读取它,例如 Textbox1.Text、Textbox2.Text、Combobox.SelectedValue(我猜) 但是,如果它在不同的页面上使用 Session 变量,例如: 会话["date1"] = TextBox1.Text; 会话["date2"] = TextBox2.Text; 会话[“comboValue”] = Combobox.SelectedValue; 并使用它们来填充您的表单

【讨论】:

  • 我正在开发完整的 C# WinApps 而不是 ASP.NET Web 应用程序。我可以在 Windows 中使用 Session 变量吗?
【解决方案3】:

【讨论】:

    【解决方案4】:

    这取决于您通常如何设计应用程序。

    • 您可以使用事件来工作 您将在其中创建的驱动系统 事件和代表。由@Dave81 提及
    • 或者您可以创建属性 返回给定/选定的值,所以 父母可以检索它们 从对象(想说Dialog 但不确定您使用的是什么)。
    • 或者你可以关注@zmilojko 将它们设为公开,这基本上是 与创建属性相同,但 更多的是编码的阴暗面 实践:D

    所有这些都可行,但这完全取决于您希望应用程序的结构。

    【讨论】:

      【解决方案5】:

      在您描述的情况下,我可能会调用frmB.ShowDialog() 而不是frmB.Show()

      // Inside FormA open frmB as a modal dialog waiting for 
      // OK or Cancel result using the following  statement
      
      if (frmB.ShowDialog() == DialogResult.OK)
      {
         // Retrieve selected values from frmB here (while frmB is still not disposed)
      }
      

      ShowDialog() 的好处是您:

      1. 轻松地从表单中获取返回值,让您确定单击“确定”(而不是“取消”)将其关闭。
      2. 表单在关闭时不会立即释放,因此您可以检索所需的值。
      3. 通过将 frmB 作为模态对话框打开,您可以避免检查用户在打开 frmB 时开始与 formA 交互时可能发生的复杂性。

      注意:在设计 frmB 时,您必须将 OK 按钮控件的 DialogResult 属性设置为 DialogResult.OK,以便在按下此按钮时表单返回正确的 DialogResult(或者也可以设置 this.DialogResult在 OK 按钮的 Click 事件处理程序中)

      【讨论】:

      • @sukumar:您尝试过这个解决方案,还是将 frmB 作为对话框打开不合适?
      • @sukumar:当您调用 frnB.ShowDialog() 时,FormA 线程不会立即执行下一条语句,而是等待 frmB 返回 DialogResult。
      【解决方案6】:

      或者您可以将一个对象从 FormA 传递到 FormB 并将其属性绑定到 FormB 中的控件。如果您希望在单击确定按钮时通知 FormA,您可以在数据容器类中声明一个事件,在 FormA 中订阅它并从 FormB 中触发它。

      成为你定义的某个类的DataContainer

      public class DataContainer
      {
          public event EventHandler AcceptedChanges;
          protected virtual void OnAcceptedChanges()
          {
              if ((this.AcceptedChanges != null))
              {
                  this.AcceptedChanges(this, EventArgs.Empty);
              }
          }
      
          public void AcceptChanges()
          {
              this.OnAcceptedChanges();
          }
      
          public string Text1 { get; set; }
          public string Text2 { get; set; }
      }
      

      在甲型中:

          private void button4_Click(object sender, EventArgs e)
      {
          DataContainer data = new DataContainer();
          data.Text1 = "text1";
          data.Text1 = "text2";
      
          Form2 frm = new Form2();
          frm.Data = new DataContainer();
          data.AcceptedChanges += new EventHandler(data_AcceptedChanges);
          frm.Show();
      }
      
      void data_AcceptedChanges(object sender, EventArgs e)
      {
          // your code here
      }
      

      在 FormB 中:

      public DataContainer Data { get; set; }
      
      private void Form2_Load(object sender, EventArgs e)
      {
          textBox1.DataBindings.Add(new Binding("Text", Data, "Text1"));
          textBox2.DataBindings.Add(new Binding("Text", Data, "Text2"));
      }
      
      private void button1_Click(object sender, EventArgs e)
      {
          Data.AcceptChanges();
      }
      

      您还应该在 DataContainer 类上实现 INotifyPropertyChanging 和 INotifyPropertyChanged 以更好地使用绑定。

      【讨论】:

      • 似乎更复杂的代码。我需要一些简单的代码来处理需求
      • @sukumar: 试试 ShowDialog() :-)
      【解决方案7】:

      您可以在 FormB 上创建一个 FormA 将订阅的 EventHandler。此外,向 FormB 添加几个公共属性,这些属性表示您希望 FormA 能够使用的数据。然后,当 FormB 触发事件时,FormA 会知道刷新他的数据。

      注意:此示例中的关键原理是实现一个 EventHandler(您可以创建自己的事件处理程序类型),当数据准备好刷新/查看/等时通知 FormA。希望这个示例能让您了解如何针对您的特定情况实现事件处理程序。

      例子:

      甲型 -

      public partial class FormA : Form
      {
          //FormA has a private instance of FormB
          private FormB formB = null;
          public FormA()
          {
              InitializeComponent();
          }
      
          void formB_OnDataAvailable(object sender, EventArgs e)
          {
              //Event handler for when FormB fires off the event
              this.label1.Text = string.Format("Text1: {0}\r\nText2: {1}", 
                  formB.Text1, formB.Text2);
          }
      
          private void InitializeFormB()
          {
              this.formB = new FormB();
      
              //FormA subscribes to FormB's event
              formB.OnDataAvailable += new EventHandler(formB_OnDataAvailable);
          }
      
          private void button1_Click(object sender, EventArgs e)
          {
              this.InitializeFormB();
              formB.Show();
          }
      }
      

      FormB -

      public partial class FormB : Form
      {
          //Event that fires when data is available
          public event EventHandler OnDataAvailable;
      
          //Properties that expose FormB's data
          public string Text1 { get; private set; }
          public string Text2 { get; private set; }
      
          public FormB()
          {
              InitializeComponent();
          }
      
          private void button1_Click(object sender, EventArgs e)
          {
              //Set the exposed properties, then fire off the event.
              this.Text1 = this.textBox1.Text;
              this.Text2 = this.textBox2.Text;
      
              if (OnDataAvailable != null)
                  OnDataAvailable(this, EventArgs.Empty);
          }
      }
      

      【讨论】:

      • 感谢 Jed,好干净的例子。
      【解决方案8】:

      我采用了简单的方法..小装饰..

      1. 在表单类中创建公共变量,即

        公共字符串 passVariable1 = "";

      2. 如果您有文本框,请转到属性,然后单击闪电并双击空的 TextChanged 事件处理程序。这将在代码开始时创建一个代码 sn-p,该代码在文本框内容更改时执行。在此代码块中,将文本框的内容分配给相应的公共变量。

      3. 即我的公共变量是

        公共字符串问题 = "";

        private void txtIssue_TextChanged(object sender, EventArgs e) { 问题 = txtIssue.Text; }

      4. 添加一个按钮并为该按钮创建一个单击事件(只需在设计窗格中双击该按钮)。在单击事件代码块中,将 dilog 结果设置为 ok 并隐藏

        this.DialogResult = DialogResult.OK;

        this.Hide();

      5. 在父窗口代码中检查对话框结果并从子窗体的公共变量中获取窗体数据

      if (f.ShowDialog() == DialogResult.OK)
        {
            string b  = f.issue;             
            string e = f.year;
            string f = f.month;
        };
      

      【讨论】:

        【解决方案9】:

        我遇到了同样的问题,并想出了一个有点不同的想法。在我的场景中,我正在为我最小的两个孩子制作一个抽认卡程序,我希望能够带回提供给父表单的答案(每个新抽认卡问题的新子表单,以便父表单可以更新有多少是左,多少正确,多少不正确等),而无需向数据库添加值。对于应该简单的事情似乎有点过分了。我所做的是创建一个包含 3 个变量类型的类。对于大多数工作,我认为每种类型的三个就足够了。

        这是我的新课程的一个例子:

        namespace ClassNamespace
        {
          public class ValueHolder
          {
            public int intValue1 { get; set; }
            public int intValue2 { get; set; }
            public int intValue3 { get; set; }
            public long longValue1 { get; set; }
            .
            .
            .
          }
        }
        

        我从父窗体创建一个新的 ValueHolder (ValueHolder vh;) 并将其传递给子窗体。在子窗体中,我创建了一个新的 ValueHolder,然后将其设置为等于在子窗体的类构造函数中发送的 ValueHolder 对象。现在,当按下回车键(给出答案)时,我可以将 vh.intValue1 设置为等于 this.answerBox.text;... 好吧,我必须使用 int.tryparse();但你明白了。然后我只需要从父表单中引用 vh.intValue1 来获取输入的值。

        父表单:

        for (int i = 0; i < limit; i++)
        {
          ValueHolder vh = new ValueHolder();
        
          ChildClass cc = new ChildClass(vh);
          MessageBox.Show(vh.intValue1.ToString()); //to test that it works
        }
        

        和子窗体:

        ValueHolder vh;
        
        public ChildClass (ValueHolder vhIncoming)
        {
          vh = vhIncoming;
        }
        
        private void answerBox_KeyDown(object sender, KeyEventArgs e)
        {
          if (e.KeyCode == Keys.Enter)
          {
            vh.intValue1 = 1234;
          }
        }
        

        这似乎是我的方案最简单的解决方案。我知道这个问题很老,但想为处于类似位置的任何人添加此选项。只需将类添加到您的项目中,根据需要将更多类型或更多类型添加到类中,然后为以后的项目冲洗重复。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-23
          • 1970-01-01
          • 1970-01-01
          • 2020-07-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-06
          相关资源
          最近更新 更多