单击按钮时在表单之间传递变量

我有两个表格。 一个用于执行所有主要代码的地方。 使用此方法单击菜单项时会显示另一个表单:

Form2 videoSettings = new Form2(); private void videoToolStripMenuItem_Click(object sender, EventArgs e) { videoSettings.Show(); } 

然后打开的表单包含用户可以为应用程序设置一些设置的字段。 在此处输入图像描述 然后单击“保存”按钮时我想要这个变量: public int deviceIndex; 从原始表格中取出。

所以我想知道我是否可以在Form1中添加任何事件或什么东西来检测在videoSettings(Form2)中点击保存按钮的时间?

我会以不同的方式做到这一点。 我将UI处理和业务逻辑层之间的代码分开。 所以你的场景将以这样的方式运行:

  1. 第一种forms发出一个事件,通知已激活具有某些语义的按钮。 处理所需的数据包含在事件的数据中。
  2. 业务逻辑侦听此事件,并决定在第二个表单上发出命令。 它在表单的类上调用一个合适的方法,将所需的信息作为参数传递(如果需要,可以预处理参数)。
  3. 第二个表单从业务逻辑接收命令并更新视图。

这样就不会出现问题了。


示例:(我不是winforms专家,请注意最佳winforms实践的POV可能完全错误。)

第1部分(第一种forms):

 class ProcessingActivatedEventArgs : EventArgs { public ProcessingActivatedEventArgs(int data) { MoreData = data; } public int MoreData { get; protected set; } } class Form1 : Form { private int currentData; public event EventHandler ProcessingActivated; void OnButtonClick(object sender, EventArgs args) { // ... if (ProcessingActivated != null) ProcessingActivated(new ProcessingActivatedEventArgs(currentData)); } } 

第2部分:(业务逻辑)

 class Controller { Form1 f1; Form2 f2; void StartFirstForm() { f1 = new Form1(); f1.ProcessingActivated += OnProcessingActivated; f1.Show(); } void OnProcessingActivated(object sender, ProcessingActivatedEventArgs args) { int data = args.MoreData; f1.DisableProcessingRequests(); model.ProcessingFinished += OnProcessingFinished; model.StartProcessing(data); if (data > 0) f2.DisplayDataProcessing(0, data); else if (data < 0) f2.DisplayDataProcessing(data, 0); else throw new SomeCoolException("impossible data"); } } 

第3部分:(第二种forms)

 class Form2 : Form { public void DisplayDataProcessing(int lower, int upper) { // ... update the UI } } 

请注意,此实现与Controller并且forms比可以实现的更紧密。 在WPF中,通过使用适当的DataContext实现解耦(但我不知道如何在WinForms中正确地执行它)。

让我建议另一种方式,即最简单的ShowDialog()和业务逻辑与接口之间分离的详细方式。

我希望在Form2中创建一个新事件。 我将此事件称为SettingsSaved

在Form2中添加为全局声明

 public delegate void SettingsSavedEventHandler(object sender, SettingsSavedEventArgs e); public event SettingsSavedEventHandler SettingsSaved; 

并在cmdSave_Click事件中

 if(SettingsSaved != null) { SettingsSavedEventArgs ss = new SettingsSavedEventArgs() { DeviceIndex = deviceIndex}; SettingsSaved(this, ss); } 

SettingsSavedEventArgs类的框架

 public class SettingsSavedEventArgs: EventArgs { public int DeviceIndex {get; set;} // Other settings could be added here } 

现在在调用Form2的代码中,我们可以订阅该事件,并在用户单击Form2 Save按钮时收到通知

 Form2 videoSettings = new Form2(); videoSettings.SettingsSaved += new SettingsSavedEventHandler(SavedHandler); videoSettings.Show(); .... private void SavedHandler(object sender, SettingsSavedEventArgs ss) { int deviceIndex = ss.DeviceIndex; } 

观察者模式

有很多建议,但我想补充两分钱。

你可以使用form2.ShowDialog(); 这将停止执行form1线程,直到form2关闭。 这意味着您可以从form1执行此操作:

 Form2 videoSettings = new Form2(); //show options videoSettings.ShowDialog(); //at this point, the user has either clicked save, cancel, or closed the form //(because the form is closed, obviously :) ) int device = videoSettings.deviceIndex; 

如果你不能像这样锁定你的表单,这是使用Form2中的事件的另一种方式:

 Form2 : Form { public event EventHandler Saved; OnSaveButtonClicked(...) { if(Saved != null) Saved(this, new EventArgs()); } } 

然后从Form1:

 Form2 frm = new Form2(); frm.Saved += (s, e) => { //saved button clicked, retrieve value. //also could be handled as a method, or really any way. }; frm.Show(); 

也许您可以尝试使用第二种forms来实现INotifyPropertyChanged接口。 然后,当您单击“保存”时,您将引发PropertyChanged事件,并以第一种forms捕获它。

您可以传递类似这样的信息

 private Form1 mainForm = null; public Form2(Form callingForm) { mainForm = callingForm as Form1; InitializeComponent(); } 

然后,您可以从Form2访问Form1属性,如下所示:

 //Call this in Save button click event this.mainForm.deviceIndex;