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

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

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

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

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

Ответ 1

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

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

то установите это внутри подформы ok нажатие кнопки

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-ключ для отмены из формы.

Ответ 2

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

 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
   }
}

Ответ 3

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

Кнопки в 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;
     }
}

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

Ответ 4

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

Ответ 5

Я использую 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
}

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

Но с вашим owr 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);

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

Ответ 6

Если вы хотите передать данные в 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

Ответ 7

Сначала вы должны определить атрибут в 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); 
  }

Ответ 8

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

Ответ 10

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

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");
    }
}

Ответ 11

Все, что вам нужно, это добавить формат "d", например:

private void NewAdmin_Form3_Load_1(object sender, EventArgs e)
{
    DateTime today = DateTime.Today;
    DateTime DateOnly = today.Date;
    DateTime answer = DateOnly.AddDays(90);
    ExitDateAdmin.Text = answer.Date.ToString("d");
}