【问题标题】:Communication between two Forms C#两个表单 C# 之间的通信
【发布时间】:2019-04-18 16:29:14
【问题描述】:

我有三个表单,它调用 Form2 和 Form2 的主表单将 Form3 作为构造函数,而对于 Form3(Form2 的构造函数)也是如此。

其实我是在尝试将Form3的信息放到Form2中。

我有一个带有信息 (Form2) 的 DataGridView,我想将信息放在文本框中 Form3 的开头。

我可以做到这一点,但我还希望通过打开 Form3 向 Form2 发送信息,以便在关闭 Form3 后在我的 DataGridView (Form2) 中创建一个新行。

在我的主窗体中:

        private void btn_gestCapteur_Click(object sender, EventArgs e)
        {
            FormGestionCapteurs fGesCapt;
            fGesCapt = new FormGestionCapteurs();

            FormGestionCapteurs fGestCapt;
            fGestCapt = new FormGestionCapteurs(fConfRes, new FormAjoutCapteur(fConfRes,fGesCapt));
            fGestCapt.ShowDialog();
        }

在我称为 FormGestionCapteurs 的 Form1 中:

        FormAjoutCapteur fAddCpt;

        FormConfigReseau fConfRes;

        public FormGestionCapteurs(FormConfigReseau fConfRes, FormAjoutCapteur fAddCpt)
        {
            InitializeComponent();

            this.fConfRes = fConfRes;

            this.fAddCpt = fAddCpt;
        }

        public FormGestionCapteurs()
        {
            InitializeComponent();
        }

在我称为 FormAjoutCapteurs 的 Form3 中:

        FormGestionCapteurs fGest;

        FormConfigReseau fConfRes;

        public FormAjoutCapteur(FormConfigReseau fConfRes, FormGestionCapteurs fGest)
        {
            InitializeComponent();

            this.fConfRes = fConfRes;

            this.fGest = fGest;
        }

        private void btn_ok_Click(object sender, EventArgs e)
        {
         DataGridViewRow row = (DataGridViewRow)fGest.tab_listeCapteurs.Rows[0].Clone(); //fGest. is the Form2 and tab_listeCapteurs is the DataGridView
                    row.Cells[0].Value = txtBox_name.Text; //These textboxes aren't empty so I want to send the text of these in the good cells of my DataGridView
                    row.Cells[1].Value = txtBox_marque.Text;
                    row.Cells[2].Value = txtBox_model.Text;
                    row.Cells[3].Value = numUpDown_calibre.Value;
                    row.Cells[4].Value = txtBox_a.Text;
                    row.Cells[5].Value = txtBox_b.Text;
                    fGest.tab_listeCapteurs.Rows.Add(row);
                    //This code doesn't effect
        }

我可以在 Form3 上发送 DataGridView 的信息,但是当我想在关闭 Form3 后在 Form2 中创建一个新行时,它不会插入该行。

【问题讨论】:

  • 什么是“Form1”?看起来没什么意思。您是在问:如何在 Form3 关闭时更新 Form2?
  • 您问题中的最后一句话令人困惑。所以你想将数据从Form3发送到Form2?
  • 我建议您创建一个包含网格中每一行的所有数据的类,然后将该类实例传递给表单以填充文本单元格。最好使用数据绑定。

标签: c# winforms


【解决方案1】:

您可以通过使用委托来做到这一点。我几乎无法理解你的问题,但我相信这会有所帮助。 只需根据您的需要修改代码。

public partial class Form3 : Form
{
    public delegate void callback_data(string dataToSend);
    public event callback_data sentIt;


   private void form3_FormClosing(object sender, FormClosingEventArgs e)
   {
       string data = "Top Secret Data";
       sentIt(data);
   }
}

现在在您创建 Form3 实例的 Form2 中调用事件。

public partial class Form2 : Form
{

   private void Form2_OnLoad()
   {
       Form2 obj = new Form2();
       obj.sentIt += onReceiveData;
       obj.ShowDialog();
   }

   private void onReceiveData(string myData)
   {
      console.WriteLine(myData);
   }
}

通过这种方式,您将获得从 Form3 到 Form2 的数据 .. 我已经尝试了 200 种新技术:p 但是这个代表是最有效的方法!相信我。

【讨论】:

    【解决方案2】:

    快速回答,见 cmets inside code。但它看起来“Form1”对您的问题没有用处。

    public partial class Form2 : Form
    {
        //No need to use constructor, this is good for a frequently open/close child form.
        private readonly FormAjoutCapteur formAjoutCapteur = new FormAjoutCapteur();
    
        public Form2()
        {
            InitializeComponent();
    
            formAjoutCapteur.FormClosed += FormAjoutCapteur_FormClosed; //this is simplest way to get inputs
            //formAjoutCapteur.BtnOK.Click += FormAjoutCapteur_BtnOK_Click; //this require the button's "Modifiers" must be "Public"
        }
    
        private void FormAjoutCapteur_FormClosed(object sender, FormClosedEventArgs e)
        {
            var text = formAjoutCapteur.textBoxInput.Text;//you can simply change the input "modifiers" as "public"
            //var obj = formAjoutCapteur.GetInputs(); // you can make a public method to return all input into an object, which is recommended.
    
            //add your row
            this.dataGridView1.Rows.Add(new DataGridViewRow());
        }
    
        private void BtnGestionCapteurs_Click(object sender, EventArgs e)
        {
            formAjoutCapteur.ShowDialog(this);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为您所拥有的是主/详细信息形式的情况。 .NET Framework 有很多内置功能来处理这类事情。我真的不了解请求的详细信息,因此这可能对您有所帮助。我还建议您阅读一本书或参加有关数据绑定的课程,因为与手动逐个文本框更新文本框和手动移动数据相比,它会让您的生活更加轻松。

      A 部分 - 主视图

      首先创建一个数据模型来表示数据网格中的每一行。从帖子中我假设了以下数据模型:

      /// <summary>
      /// Defines a Capteurs
      /// </summary>
      public class Capteurs : ICloneable
      {
          public Capteurs()
          {
              this.Name=  string.Empty;
              this.Marque=  string.Empty;
              this.Model=  string.Empty;
              this.Calibre=  0;
              this.A=  string.Empty;
              this.B=  string.Empty;
          }
          public Capteurs(Capteurs other)
          {
              this.Name = other.Name;
              this.Marque = other.Marque;
              this.Model = other.Model;
              this.Calibre= other.Calibre;
              this.A=other.A;
              this.B=other.B; 
          }
      
          public string Name { get; set; }
          public string Marque { get; set; }
          public string Model { get; set; }
          public int Calibre { get; set; }
          public string A { get; set; }
          public string B { get; set; }
      
          #region ICloneable Members
          public Capteurs Clone() => new Capteurs(this);
          object ICloneable.Clone() => Clone();
          #endregion
      
      }
      

      注意到我实现了ICloneable 以复制数据,因此除非我愿意,否则我不会干扰主列表。

      接下来我在基于这个类的项目中添加了一个数据源

      主表单包含一个DataGridView 以显示链接到数据源的所有数据

      现在,当表单加载时,我使用 capteursBindingSource.DataSource = list; 将数据添加到数据源,项目列表显示在主表单上。

      将以下属性添加到主表单,以便访问当前选定的项目、列表管理器、项目列表和当前项目的索引。

      public Capteurs Current
      {
          get => List[Index];
          set => List[Index] = value;
      }
      public CurrencyManager CurrencyManager 
      { 
          get => BindingContext[capteursBindingSource] as CurrencyManager; 
      }
      public IList<Capteurs> List 
      { 
          get => capteursBindingSource.DataSource as IList<Capteurs>; 
      }
      public int Index
      {
          get => BindingContext[capteursBindingSource].Position;
          set => BindingContext[capteursBindingSource].Position = value;
      }
      

      B 部分 - 详细视图

      创建第二个表单并将数据源拖到表单的表面

      删除定位工具栏(因为您一次只显示一组数据)。组织创建的控件,并添加 OK/Cancel 或 Accept/Close 按钮​​,以指示编辑是否正确。

      最后,添加以下属性以获取或设置要在表单中显示的数据

      public Capteurs Current
      {
          get => BindingContext[capteursBindingSource].Current as Capteurs;
          set => capteursBindingSource.DataSource = new Capteurs[] { value };
      }
      

      C 部分 - 链接表单

      上述所有操作都是为了简化表单之间的数据传输。在主表单中,以下按钮处理程序打开详细表单,发送当前数据的克隆,如果用户选择 [保留],则编辑的数据将存储回主列表并刷新网格 使用CurrencyManager.Refresh() 命令。

      private void detailsButton_Click(object sender, EventArgs e)
      {
          var dlg = new DetaillForm();
          dlg.Current = this.Current.Clone();
      
          if (dlg.ShowDialog(this) == DialogResult.OK)
          {
              this.Current = dlg.Current;
              CurrencyManager.Refresh();
          }
      }
      

      【讨论】:

      • 这很努力,但是来吧,它是开箱即用的!您应该做的是详细说明问题到底是什么,而不是花一天时间提供替代解决方案。他的问题没有得到回答:如何在表单之间传递值?但是你给他更多的问题:形式之间的绑定有什么魔力?如果他想使用此解决方案验证详细信息表单该怎么办?如果数据表与网格视图不同,如何绑定?等等……
      • 我认为dlg.Current = this.Current.Clone(); 回答了这个问题,这就是值如何从一种形式转移到另一种形式。这也是C#,但 OP 没有数据模型。我认为这是错误的方法,我的回答指向更好的解决策略。
      猜你喜欢
      • 1970-01-01
      • 2020-10-17
      • 2016-07-27
      • 1970-01-01
      • 1970-01-01
      • 2018-06-05
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多