Comment renvoyer une valeur à partir d'un formulaire en C #?

185

J'ai un formulaire principal (appelons-le frmHireQuote) qui est un enfant d'un formulaire MDI principal (frmMainMDI), qui montre un autre formulaire (frmImportContact) via ShowDialog () lorsqu'un bouton est cliqué.

Lorsque l'utilisateur clique sur «OK» sur frmImportContact, je souhaite renvoyer quelques variables de chaîne à certaines zones de texte sur frmHireQuote.

Notez qu'il pourrait y avoir plusieurs instances de frmHireQuote, il est évidemment important que je revienne à l'instance qui a appelé cette instance de frmImportContact.

Quelle est la meilleure méthode pour y parvenir?

Jez Clark
la source

Réponses:

367

Créez des propriétés publiques sur votre sous-formulaire comme ceci

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

puis définissez ceci dans votre sous-formulaire ok button click handler

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

Puis dans votre formulaire frmHireQuote , lorsque vous ouvrez le sous-formulaire

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

De plus, si vous souhaitez annuler le sous-formulaire, vous pouvez simplement ajouter un bouton au formulaire et définir son DialogResult sur Cancelet vous pouvez également définir la propriété CancelButton du formulaire sur ledit bouton - cela permettra à la touche d'échappement d'annuler de la forme.

Richard Friend
la source
33
Quelques défauts importants. Un formulaire affiché avec ShowDialog () n'est pas supprimé. Vous devez utiliser l' instruction using ici. ShowDialog () renvoie une valeur DialogResult, ne l'ignorez pas ou vous essaierez d'utiliser les propriétés de la boîte de dialogue lorsque l'utilisateur a annulé la boîte de dialogue.
Hans Passant
Cheers, j'ai expliqué cela.
Jez Clark
Mini-critique: l'ensemble nécessite l'ajout d'un point-virgule.
B. Clay Shannon
16

Je crée normalement une méthode statique sur formulaire / dialogue, que je peux appeler. Cela renvoie le succès (bouton OK) ou l'échec, ainsi que les valeurs à renseigner.

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


 }

Et sur le formulaire:

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

Pour appeler votre formulaire;

public void MyEventToCallForm() {
   var result = frmMain.Execute();
   if (result.Result == DialogResult.OK) {
       myTextBox.Text = result.Field1; // or something like that
   }
}
GvS
la source
Ont utilisé cette approche aussi, fonctionne bien. Cependant, le préfixe de la classe de résultat avec frmcan (et vient de le faire quand je l'ai lu) conduit à la confusion ...
Richard Friend
Je viens de réutiliser le nom de la question (+ saisie rapide). Je vais le changer pour un meilleur nom.
GvS
6

J'ai trouvé un autre petit problème avec ce code ... ou du moins c'était problématique quand j'ai essayé de l'implémenter.

Les boutons de frmMain ne renvoient pas de valeur compatible, en utilisant VS2010, j'ai ajouté ce qui suit et tout a commencé à fonctionner correctement.

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

Après avoir ajouté les deux valeurs de bouton, la boîte de dialogue a très bien fonctionné! Merci pour l'exemple, cela a vraiment aidé.

DaveHelton
la source
1

Je viens de mettre quelque chose dans le constructeur par référence, afin que le sous-formulaire puisse changer sa valeur et que le formulaire principal puisse obtenir un objet nouveau ou modifié à partir du sous-formulaire.

SerG
la source
0

J'utilise beaucoup MDI, je l'aime beaucoup plus (où il peut être utilisé) que plusieurs formulaires flottants.

Mais pour en tirer le meilleur parti, vous devez vous familiariser avec vos propres événements. Cela vous rend la vie tellement plus facile.

Un exemple squelettique.

Ayez vos propres types d'interruptions,

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

Ensuite, votre propre type 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; }

}

Ensuite, utilisez le délégué dans votre espace de noms, mais en dehors d'une classe

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

Maintenant, manuellement ou à l'aide de l'interface graphique, demandez au MDIparent de répondre aux événements des formulaires enfants.

Mais avec votre owr Args, vous pouvez réduire cela à une seule fonction. et vous pouvez avoir la possibilité d'interrompre les interruptions, bon pour le débogage, mais peut être utile à d'autres égards.

Faites simplement pointer tous vos codes d'événement mdiparent vers une fonction,

        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 simple mécanisme de commutation suffit généralement pour transmettre les événements aux formulaires appropriés.

Bob
la source
0

Si vous voulez passer des données à form2de form1sans passer comme neufform(sting "data");

Faites comme ça sous la forme 1

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

sous forme 2 ajouter

public string ReturnValue1 { get; set; }

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

Vous pouvez également utiliser une valeur form1comme celle-ci si vous souhaitez échanger quelque chose dansform1

juste en forme1

textbox.Text =form2.ReturnValue1
Matas Lesinskas
la source
0

Vous devez d'abord définir l'attribut dans form2 (enfant), vous mettrez à jour cet attribut dans form2 et aussi à partir de 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";
 }

Appel de form2 (enfant) depuis 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
la source
0

Je lève un événement dans le formulaire définissant la valeur et je m'abonne à cet événement dans le (s) formulaire (s) qui doivent gérer le changement de valeur.

Edward Miller
la source
Héy! Pouvez-vous élaborer un peu plus sur votre réponse et éventuellement fournir un exemple de code pour aider les futurs utilisateurs?
Jeremy Harris
0

les délégués sont la meilleure option pour envoyer des données d'un formulaire à un autre.

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");
    }
}
Dit Muhammad Idrees
la source