Come restituire un valore da un modulo in C #?

Ho un modulo principale (chiamiamolo frmHireQuote) che è figlio di un modulo MDI principale (frmMainMDI), che mostra un altro modulo (frmImportContact) tramite ShowDialog () quando viene cliccato un pulsante.

Quando l’utente fa clic su “OK” su frmImportContact, voglio passare alcune variabili stringa in alcune caselle di testo su frmHireQuote.

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

Qual è il miglior metodo per farlo?

Creare alcune proprietà pubbliche nel sottomodulo in questo modo

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

quindi impostalo nel gestore di clic del pulsante ok della sottotabella

 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 tuo modulo frmHireQuote , quando apri la sottomaschera

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

Addizionalmente, se si desidera annullare il sottomodulo, è sufficiente aggiungere un pulsante al modulo e impostare il suo DialogResult su Cancel e impostare anche la proprietà CancelButton del modulo su detto pulsante: ciò consente di annullare la chiave di escape fuori dalla forma.

Generalmente creo un metodo statico su form / dialog, che posso chiamare. Ciò restituisce il successo (pulsante OK) o il fallimento, 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 modulo;

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

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

I pulsanti di frmMain non restituiscono un valore compatibile, utilizzando VS2010 ho aggiunto quanto segue e tutto ha funzionato 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 dei pulsanti, il dialogo ha funzionato alla grande! Grazie per l’esempio, mi ha davvero aiutato.

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

Uso MDI parecchio, mi piace molto di più (dove può essere usato) di più forms mobili.

Ma per ottenere il meglio da esso è necessario fare i conti con i propri eventi. Ti rende la vita molto più facile per te.

Un esempio scheletrico.

Hai i tuoi tipi di interrupt,

 //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 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 utilizzare il delegato all’interno del proprio spazio dei nomi, ma al di fuori di una class

 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 si può avere il provisioning per interrompere le interruzioni, buono per il debug, ma può essere utile anche in altri modi.

Basta che tutti i tuoi codici evento mdiparent puntino a una 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.

Se si desidera passare dati a form2 da form1 senza passare come nuovo form(sting "data");

Fai così nel modulo 1

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

nel modulo 2 aggiungi

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

Inoltre è ansible utilizzare il valore in form1 come questo se si desidera scambiare qualcosa in form1

solo in forma1

 textbox.Text =form2.ReturnValue1 

Per prima cosa devi definire l’attributo in form2 (figlio) 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 (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); }