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

时间:2012-07-01 16:59:50

标签: c# .net winforms parameter-passing

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

Form2 videoSettings = new Form2();       

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

然后打开的表单包含用户可以为应用程序设置一些设置的字段。 enter image description here 然后点击“保存”按钮我想要这个变量:public int deviceIndex; 从原始表格中取出。

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

5 个答案:

答案 0 :(得分:6)

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

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


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

    第1部分(第一种形式):

    class ProcessingActivatedEventArgs : EventArgs
    {
        public ProcessingActivatedEventArgs(int data) { MoreData = data; }
        public int MoreData { get; protected set; }
    }
    
    class Form1 : Form
    {
        private int currentData;
        public event EventHandler<ProcessingActivatedEventArgs> 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部分:(第二种形式)

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

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

答案 1 :(得分:1)

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

你可以使用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();

答案 2 :(得分:1)

让我建议另一种方式,即最简单的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;
}

Observer Pattern

答案 3 :(得分:0)

也许您可以尝试使用第二种形式来实现INotifyPropertyChanged界面。然后,当您单击“保存”时,您可以提高 PropertyChanged 事件,并以第一种形式捕获它。

答案 4 :(得分:0)

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

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;