Как вернуть значение из формы в C #?

185

У меня есть основная форма (назовем ее frmHireQuote), которая является дочерней по отношению к основной форме MDI (frmMainMDI), которая показывает другую форму (frmImportContact) через ShowDialog () при нажатии кнопки.

Когда пользователь нажимает «ОК» на frmImportContact, я хочу передать несколько строковых переменных обратно в некоторые текстовые поля в frmHireQuote.

Обратите внимание, что может быть несколько экземпляров frmHireQuote, очевидно, что важно вернуться к экземпляру, который вызвал этот экземпляр frmImportContact.

Какой лучший способ сделать это?

Джез Кларк
источник

Ответы:

367

Создайте несколько открытых свойств на ваш суб-форме как так

public string ReturnValue1 {get;set;} 
public string ReturnValue2 {get;set;}

затем установите это в вашей под-форме обработчик нажатия кнопки ОК

private void btnOk_Click(object sender,EventArgs e)
{
    this.ReturnValue1 = "Something";
    this.ReturnValue2 = DateTime.Now.ToString(); //example
    this.DialogResult = DialogResult.OK;
    this.Close();
}

Затем в форме frmHireQuote , когда вы открываете подформу

using (var form = new frmImportContact())
{
    var result = form.ShowDialog();
    if (result == DialogResult.OK)
    {
        string val = form.ReturnValue1;            //values preserved after close
        string dateString = form.ReturnValue2;
        //Do something here with these values

        //for example
        this.txtSomething.Text = val;
    }
}

Кроме того, если вы хотите отменить из формы, вы можете просто добавить кнопку в форму и установить ее DialogResult в значение, Cancelи вы также можете установить свойство CancelButton формы для указанной кнопки - это позволит клавише escape отменить формы.

Ричард Френд
источник
33
Пара важных недостатков. Форма, отображаемая с помощью ShowDialog (), не удаляется. Вы должны использовать оператор использования здесь. ShowDialog () возвращает значение DialogResult, не игнорируйте его, или вы попытаетесь использовать свойства диалога, когда пользователь отменил диалог.
Ганс Пассант
Ура, я учел это.
Джез Кларк
Мини-критика: необходимо добавить точку с запятой.
Б. Клэй Шеннон
16

Я обычно создаю статический метод в форме / диалоге, который я могу вызвать. Это возвращает успех (кнопка ОК) или неудачу вместе со значениями, которые необходимо заполнить.

 public class ResultFromFrmMain {
     public DialogResult Result { get; set; }
     public string Field1 { get; set; }


 }

И на форме:

public static ResultFromFrmMain Execute() {
     using (var f = new frmMain()) {
          var result = new ResultFromFrmMain();
          result.Result = f.ShowDialog();
          if (result.Result == DialogResult.OK) {
             // fill other values
          }
          return result;
     }
}

Позвонить в вашу форму;

public void MyEventToCallForm() {
   var result = frmMain.Execute();
   if (result.Result == DialogResult.OK) {
       myTextBox.Text = result.Field1; // or something like that
   }
}
GvS
источник
Использовали этот подход также, работает хорошо. Однако добавление префикса к классу результатов с помощью frmcan (и только что, когда я его прочитал) приводит к путанице ...
Ричард Френд
Я просто повторно использовал имя из вопроса (+ быстрая печать). Я изменю это на лучшее имя.
GvS
6

Нашел еще одну небольшую проблему с этим кодом ... или, по крайней мере, это было проблематично, когда я пытался его реализовать.

Кнопки в frmMain не возвращают совместимое значение, используя VS2010, я добавил следующее, и все стало работать нормально.

public static ResultFromFrmMain Execute() {
     using (var f = new frmMain()) {

          f.buttonOK.DialogResult = DialogResult.OK;
          f.buttonCancel.DialogResult = DialogResult.Cancel;

          var result = new ResultFromFrmMain();
          result.Result = f.ShowDialog();

          if (result.Result == DialogResult.OK) {
             // fill other values
          }
          return result;
     }
}

После добавления значений двух кнопок диалог работал отлично! Спасибо за пример, это действительно помогло.

DaveHelton
источник
1

Я просто помещаю в конструктор что-то по ссылке, чтобы подчиненная форма могла изменить свое значение, а основная форма могла получить новый или измененный объект из подчиненной формы.

SerG
источник
0

Я использую MDI довольно много, мне это нравится гораздо больше (где его можно использовать), чем несколько плавающих форм.

Но чтобы извлечь из этого максимум, вам нужно разобраться с собственными событиями. Это делает жизнь намного проще для вас.

Пример скелета.

Иметь свои собственные типы прерываний,

//Clock, Stock and Accoubts represent the actual forms in
//the MDI application. When I have multiple copies of a form
//I also give them an ID, at the time they are created, then
//include that ID in the Args class.
public enum InteruptSource
{
    IS_CLOCK = 0, IS_STOCKS, IS_ACCOUNTS
}
//This particular event type is time based,
//but you can add others to it, such as document
//based.
public enum EVInterupts
{
    CI_NEWDAY = 0, CI_NEWMONTH, CI_NEWYEAR, CI_PAYDAY, CI_STOCKPAYOUT, 
   CI_STOCKIN, DO_NEWEMAIL, DO_SAVETOARCHIVE
}

Тогда ваш собственный тип Args

public class ControlArgs
{
    //MDI form source
    public InteruptSource source { get; set; }
    //Interrupt type
    public EVInterupts clockInt { get; set; }
    //in this case only a date is needed
    //but normally I include optional data (as if a C UNION type)
    //the form that responds to the event decides if
    //the data is for it.
    public DateTime date { get; set; }
    //CI_STOCKIN
    public StockClass inStock { get; set; }

}

Затем используйте делегата в вашем пространстве имен, но вне класса

namespace MyApplication
{
public delegate void StoreHandler(object sender, ControlArgs e);
  public partial class Form1 : Form
{
  //your main form
}

Теперь вручную или с помощью графического интерфейса попросите MDIparent реагировать на события дочерних форм.

Но с вашим Args, вы можете уменьшить это до одной функции. и вы можете иметь возможность прерывать прерывания, что хорошо для отладки, но может быть полезно и в других отношениях.

Просто пусть все ваши коды событий mdiparent указывают на одну функцию,

        calendar.Friday += new StoreHandler(MyEvents);
        calendar.Saturday += new StoreHandler(MyEvents);
        calendar.Sunday += new StoreHandler(MyEvents);
        calendar.PayDay += new StoreHandler(MyEvents);
        calendar.NewYear += new StoreHandler(MyEvents);

Простого механизма переключения обычно достаточно для передачи событий в соответствующие формы.

боб
источник
0

Если вы хотите передать данные form2из form1без передачи, как новыйform(sting "data");

Делай так в форме 1

using (Form2 form2= new Form2())
{
   form2.ReturnValue1 = "lalala";
   form2.ShowDialog();
}

в форму 2 добавить

public string ReturnValue1 { get; set; }

private void form2_Load(object sender, EventArgs e)
{
   MessageBox.Show(ReturnValue1);
}

Также вы можете использовать значение в form1этом, если вы хотите поменять что-то вform1

только в форме1

textbox.Text =form2.ReturnValue1
Матас Лесинскас
источник
0

Сначала вы должны определить атрибут в form2 (дочерний), вы обновите этот атрибут в form2, а также из form1 (родительский):

 public string Response { get; set; }

 private void OkButton_Click(object sender, EventArgs e)
 {
    Response = "ok";
 }

 private void CancelButton_Click(object sender, EventArgs e)
 {
    Response = "Cancel";
 }

Вызов form2 (child) из form1 (parent):

  using (Form2 formObject= new Form2() )
  {
     formObject.ShowDialog();

      string result = formObject.Response; 
      //to update response of form2 after saving in result
      formObject.Response="";

      // do what ever with result...
      MessageBox.Show("Response from form2: "+result); 
  }
Ваджид хан
источник
0

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

Эдвард Миллер
источник
Привет всем! Можете ли вы подробнее рассказать о своем ответе и, возможно, предоставить пример кода, чтобы помочь будущим пользователям?
Джереми Харрис
0

делегаты - лучший вариант для отправки данных из одной формы в другую.

public partial class frmImportContact : Form
{
     public delegate void callback_data(string someData);
    public event callback_data getData_CallBack;

    private void button_Click(object sender, EventArgs e)
    {
      string myData = "Top Secret Data To Share";
      getData_CallBack(myData);
    }

}

public partial class frmHireQuote : Form
{
     private void Button_Click(object sender, EventArgs e)
    {

      frmImportContact obj = new frmImportContact();
      obj.getData_CallBack += getData;
    }

    private void getData(string someData)
    {
         MessageBox.Show("someData");
    }
}
Сказал Мухаммед Идриес
источник