单击按钮时在表单之间传递变量
我有两个表格。 一个用于执行所有主要代码的地方。 使用此方法单击菜单项时会显示另一个表单:
Form2 videoSettings = new Form2(); private void videoToolStripMenuItem_Click(object sender, EventArgs e) { videoSettings.Show(); }
然后打开的表单包含用户可以为应用程序设置一些设置的字段。 然后单击“保存”按钮时我想要这个变量: public int deviceIndex;
从原始表格中取出。
所以我想知道我是否可以在Form1中添加任何事件或什么东西来检测在videoSettings(Form2)中点击保存按钮的时间?
我会以不同的方式做到这一点。 我将UI处理和业务逻辑层之间的代码分开。 所以你的场景将以这样的方式运行:
- 第一种forms发出一个事件,通知已激活具有某些语义的按钮。 处理所需的数据包含在事件的数据中。
- 业务逻辑侦听此事件,并决定在第二个表单上发出命令。 它在表单的类上调用一个合适的方法,将所需的信息作为参数传递(如果需要,可以预处理参数)。
- 第二个表单从业务逻辑接收命令并更新视图。
这样就不会出现问题了。
示例:(我不是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;