Come restituire un valore da un modulo in C #?


185

Ho un modulo principale (chiamiamolo frmHireQuote) che è figlio di un modulo MDI principale (frmMainMDI), che mostra un altro modulo (frmImportContact) tramite ShowDialog () quando si fa clic su un pulsante.

Quando l'utente fa clic su "OK" su frmImportContact, desidero restituire alcune variabili di stringa ad alcune caselle di testo su frmHireQuote.

Nota che potrebbero esserci più istanze di frmHireQuote, è ovviamente importante tornare all'istanza che ha chiamato questa istanza di frmImportContact.

Qual è il metodo migliore per farlo?

Risposte:


367

Crea alcune proprietà pubbliche sul tuo sottomodulo in questo modo

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

quindi impostalo all'interno del gestore di clic del pulsante ok del sottomodulo

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

Quindi, nel modulo frmHireQuote , quando si apre il modulo secondario

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

Inoltre, se desideri annullare il modulo secondario, puoi semplicemente aggiungere un pulsante al modulo e impostare DialogResult su Cancele puoi anche impostare la proprietà CancelButton del modulo su detto pulsante: ciò consentirà al tasto Esc di annullare del modulo.


33
Un paio di difetti importanti. Un modulo visualizzato con ShowDialog () non è eliminato. È necessario utilizzare l' istruzione using qui. ShowDialog () restituisce un valore DialogResult, non ignorarlo o proverai a utilizzare le proprietà della finestra di dialogo quando l'utente ha annullato la finestra di dialogo.
Hans Passant

Saluti, ho tenuto conto di questo.
Jez Clark,

Mini-critica: il set richiede il punto e virgola aggiunto.
B. Clay Shannon,

16

Normalmente creo un metodo statico su form / dialog, che posso chiamare. Ciò restituisce l'esito positivo (pulsante OK) o l'errore, insieme ai valori che devono essere compilati.

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


 }

E sul modulo:

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

Per chiamare il tuo modulo;

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

Ho usato anche questo approccio, funziona bene. Tuttavia il prefisso della classe di risultati con frmcan (e appena fatto quando l'ho letto) porta alla confusione ...
Richard Friend

Ho appena riutilizzato il nome dalla domanda (+ digitazione veloce). Lo cambierò con un nome migliore.
GvS

6

Trovato un altro piccolo problema con questo codice ... o almeno è stato problematico quando ho provato a implementarlo.

I pulsanti in frmMain non restituiscono un valore compatibile, utilizzando VS2010 ho aggiunto quanto segue e tutto ha iniziato a funzionare correttamente.

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

Dopo aver aggiunto i due valori del pulsante, la finestra di dialogo ha funzionato alla grande! Grazie per l'esempio, mi ha davvero aiutato.


1

Ho appena messo nel costruttore qualcosa per riferimento, quindi la sottomaschera può cambiare il suo valore e la forma principale può ottenere oggetti nuovi o modificati dalla sottomaschera.


0

Uso MDI abbastanza, mi piace molto di più (dove può essere utilizzato) rispetto a più forme mobili.

Ma per ottenere il meglio da esso, devi fare i conti con i tuoi eventi. Ti semplifica la vita.

Un esempio scheletrico.

Hai i tuoi tipi di interruzione,

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

Quindi il tuo tipo di 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; }

}

Quindi usa il delegato nel tuo spazio dei nomi, ma al di fuori di una classe

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

Ora manualmente o utilizzando la GUI, fare in modo che MDIparent risponda agli eventi dei moduli figlio.

Ma con il tuo owr Args, puoi ridurlo a una singola funzione. e puoi provvedere a interrompere le interruzioni, buono per il debug, ma può essere utile anche in altri modi.

Basta che tutti i tuoi codici evento mdiparent puntino all'unica funzione,

        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 semplice meccanismo di commutazione è in genere sufficiente per trasmettere gli eventi ai moduli appropriati.


0

Se si desidera passare i dati form2da form1senza passare come nuoviform(sting "data");

Fai come quello nel modulo 1

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

nel modulo 2 aggiungere

public string ReturnValue1 { get; set; }

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

Inoltre puoi usare il valore in form1questo modo se vuoi scambiare qualcosaform1

solo in form1

textbox.Text =form2.ReturnValue1

0

Per prima cosa devi definire l'attributo in form2 (child) aggiornerai questo attributo in form2 e anche da form1 (parent):

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

Chiamata di form2 (figlio) da form1 (padre):

  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

Sollevo un evento nel modulo che imposta il valore e sottoscrivo quell'evento nei moduli che devono gestire la modifica del valore.


Ehilà! Puoi approfondire un po 'di più la tua risposta e possibilmente fornire un esempio di codice per aiutare i futuri utenti?
Jeremy Harris,

0

i delegati sono l'opzione migliore per l'invio di dati da un modulo a un altro.

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");
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.