¿Cómo devolver un valor de un formulario en C #?

Tengo un formulario principal (llamémoslo frmHireQuote) que es un elemento secundario de un formulario principal de MDI (frmMainMDI), que muestra otro formulario (frmImportContact) a través de ShowDialog () cuando se hace clic en un botón.

Cuando el usuario hace clic en ‘Aceptar’ en frmImportContact, quiero pasar algunas variables de cadena a algunos cuadros de texto en frmHireQuote.

Tenga en cuenta que podría haber varias instancias de frmHireQuote, obviamente es importante que regrese a la instancia que llamó a esta instancia de frmImportContact.

¿Cuál es el mejor método para hacer esto?

Crea algunas propiedades públicas en tu subformulario como tal

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

a continuación, configure esto dentro de su subformulario botón Aceptar haga clic en controlador

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

Luego, en su formulario frmHireQuote , cuando abra el formulario secundario

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

Además, si desea cancelar el formulario secundario, puede simplemente agregar un botón al formulario y establecer su DialogResult en Cancel y también puede establecer la propiedad CancelButton del formulario en dicho botón; esto permitirá que la tecla de escape se cancele. fuera de la forma.

Normalmente creo un método estático en formulario / diálogo, al que puedo llamar. Esto devuelve el éxito (botón Aceptar) o falla, junto con los valores que deben completarse.

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

Y en la forma:

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

Para llamar a tu formulario;

 public void MyEventToCallForm() { var result = frmMain.Execute(); if (result.Result == DialogResult.OK) { myTextBox.Text = result.Field1; // or something like that } } 

Encontré otro pequeño problema con este código … o al menos fue problemático cuando traté de implementarlo.

Los botones en frmMain no devuelven un valor compatible, usando VS2010 Agregué lo siguiente y todo comenzó a funcionar bien.

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

Después de agregar los dos valores de los botones, ¡el diálogo funcionó de maravilla! Gracias por el ejemplo, realmente ayudó.

Acabo de poner en el constructor algo por referencia, por lo que el subformulario puede cambiar su valor y la forma principal puede obtener un objeto nuevo o modificado del subformulario.

Uso MDI bastante, me gusta mucho más (donde puede usarse) que múltiples formas flotantes.

Pero para obtener lo mejor de ello, debe familiarizarse con sus propios eventos. Hace la vida mucho más fácil para ti.

Un ejemplo esquelético.

Tienes tus propios tipos de interupt,

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

Entonces tu propio tipo de 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; } } 

Luego usa el delegado dentro de tu espacio de nombres, pero fuera de una clase

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

Ahora, ya sea manualmente o usando la GUI, haga que MDIparent responda a los eventos de los formularios secundarios.

Pero con su ow Args, puede reducir esto a una sola función. y puede tener provisión para interrumpir las interrupciones, es bueno para la depuración, pero también puede ser útil de otras maneras.

Simplemente haga que todos sus códigos de evento mdiparent apunten a la función única,

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

Un mecanismo de cambio simple suele ser suficiente para pasar los eventos a las formas apropiadas.

Si desea pasar datos a form2 desde form1 sin pasar como nuevo form(sting "data");

Hazlo así en la forma 1

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

en el formulario 2 agregar

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

También puedes usar value en form1 como este si quieres cambiar algo en form1

solo en form1

 textbox.Text =form2.ReturnValue1 

Primero debe definir el atributo en form2 (secundario) y actualizará este atributo en form2 y también en form1 (principal):

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

Llamada de form2 (child) desde 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); }