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

185

Tengo un formulario principal (llamémoslo frmHireQuote) que es hijo de un formulario MDI principal (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?

Jez Clark
fuente

Respuestas:

367

Cree algunas propiedades públicas en su subformulario de esta manera

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

luego configúrelo dentro de su subformulario ok botón 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 subformulario

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

Adicionalmente, si desea cancelar el sub-forma que sólo puede añadir un botón al formulario y establezca su DialogResult a Cancely también se puede ajustar la CancelButton propiedad del formulario a dicho botón - esto permitirá que la tecla de escape para cancelar de la forma.

Richard Friend
fuente
33
Un par de fallas importantes. Un formulario que se muestra con ShowDialog () no se elimina. Debe usar la declaración de uso aquí. ShowDialog () devuelve un valor DialogResult, no lo ignore o intentará usar las propiedades del diálogo cuando el usuario cancele el diálogo.
Hans Passant
Saludos, he contado esto.
Jez Clark
Minicrítica: el conjunto necesita un punto y coma agregado.
B. Clay Shannon
16

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

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


 }

Y en el formulario:

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
   }
}
GvS
fuente
Han utilizado este enfoque también, funciona bien. Sin embargo, el prefijo de la clase de resultado con frmcan (y lo hice cuando lo leí) conduce a confusión ...
Richard Friend
Acabo de reutilizar el nombre de la pregunta (+ escritura rápida). Lo cambiaré a un mejor nombre.
GvS
6

Encontré otro pequeño problema con este código ... o al menos fue problemático cuando intenté 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 botón, el diálogo funcionó muy bien Gracias por el ejemplo, realmente ayudó.

DaveHelton
fuente
1

Acabo de poner algo en el constructor por referencia, para que el subformulario pueda cambiar su valor y el formulario principal pueda obtener un objeto nuevo o modificado del subformulario.

SerG
fuente
0

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

Pero para obtener lo mejor de ti, debes familiarizarte con tus propios eventos. Te hace la vida mucho más fácil.

Un ejemplo esquelético.

Ten tus propios tipos de interrupción,

//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 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 use el delegado dentro de su 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 utilizando la GUI, haga que el MDIparent responda a los eventos de los formularios secundarios.

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

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

        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 eventos a los formularios apropiados.

Beto
fuente
0

Si desea pasar datos form2desde form1sin pasar como nuevoform(sting "data");

Haz eso en la forma 1

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

en forma 2 agregar

public string ReturnValue1 { get; set; }

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

También puede usar el valor de form1esta manera si desea intercambiar algo enform1

solo en forma1

textbox.Text =form2.ReturnValue1
Matas Lesinskas
fuente
0

Primero debe definir el atributo en form2 (hijo), actualizará este atributo en form2 y también desde form1 (padre):

 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); 
  }
Wajid khan
fuente
0

Levanto un evento en el formulario estableciendo el valor y me suscribo a ese evento en el formulario (s) que necesitan lidiar con el cambio de valor.

Edward Miller
fuente
¡Hola! ¿Puede elaborar un poco más sobre su respuesta y posiblemente proporcionar una muestra de código para ayudar a los futuros usuarios?
Jeremy Harris
0

Los delegados son la mejor opción para enviar datos de un formulario a otro.

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");
    }
}
Sayed Muhammad Idrees
fuente