2012-07-01 2 views
2

У меня есть две формы. Один, где выполняется весь основной код. А другая форма отображается при нажатии на пункт меню с помощью этого метода:Передать переменную между формами при нажатии кнопки

Form2 videoSettings = new Form2();  

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

формы, который затем открыл containsfields, где пользователь получает установить некоторые параметры приложения. enter image description here Затем, нажав кнопку «Сохранить», я хочу эту переменную: public int deviceIndex; , чтобы быть извлеченной из оригинальной формы.

Так что мне интересно, могу ли я добавить какое-либо событие или что-то в Form1, который обнаруживает, когда нажата кнопка сохранения в настройках videoSettings (Form2)?

ответ

6

Я бы сделал это по-другому. Я бы разделил код между обработкой пользовательского интерфейса и уровнями бизнес-логики. Таким образом, ваш сценарий будет работать таким образом:

  1. В первой форме выдается событие, уведомляющее, что кнопка с определенной семантикой активирована. Данные, необходимые для обработки, включаются в данные события.
  2. Бизнес-логика слушает это событие и решает выдать команду во второй форме. Он вызывает соответствующий метод в классе формы, передавая необходимую информацию в качестве параметра (и, возможно, предварительно обрабатывая параметр, если это необходимо).
  3. Вторая форма получает команду из бизнес-логики и обновляет представление.

Таким образом, проблема не возникает вообще.


Пример: (я не эксперт WinForms, остерегайтесь это может быть совершенно неправильно от POV лучших практик WinForms.)

Часть 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).

+0

Можете ли вы предоставить простой пример кода? –

+0

Это действительно звучит намного лучше! Есть ли у вас какой-либо пример с этой версией? Или вы можете ссылаться на что-то знакомое, поэтому я просто понимаю его. – jimutt

+0

@Robert: Я не эксперт по winforms, поэтому я не знаю, что такое идиоматический способ выражения отношений между взглядом и бизнес-логикой. Но я попытаюсь. – Vlad

0

Возможно, вам понравится ваша вторая форма для реализации интерфейса INotifyPropertyChanged. Затем, когда вы нажимаете «Сохранить», вы поднимаете событие PropertyChanged, и вы фиксируете его в первой форме.

+0

для не-французской версии: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged% 28v = VS.80% 29.aspx – caesay

+0

К сожалению, спасибо ^^ – GianT971

0

Вы можете передать информацию о что-то вроде этого

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

Затем, вы можете получить доступ к свойству Form1 из Form2 так:

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

Ему нужно только это свойство, поэтому зачем продолжать всю форму. Если бы я был вами, я бы использовал интерфейс. – HichemSeeSharp

+0

Могут быть альтернативы, интерфейс может обеспечить лучшее решение. Я просто дал все, что мог. –

1

Есть много предложений, но я хотел бы добавить мои два цента.

Вы можете использовать form2.ShowDialog(); который остановит выполнение вашей формы1 до тех пор, пока форма 2 не будет закрыта. Это означает, что вы можете просто сделать это из 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(); 
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

Form2 videoSettings = new Form2(); 
videoSettings.SettingsSaved += new SettingsSavedEventHandler(SavedHandler); 
videoSettings.Show();  
.... 

private void SavedHandler(object sender, SettingsSavedEventArgs ss) 
{ 
    int deviceIndex = ss.DeviceIndex; 
} 

Observer Pattern

+0

Это как мой второй пример, кроме как с большим количеством кода :) – caesay

Смежные вопросы