Wie kann ich einen Wert aus einem Formular in C # zurückgeben?

185

Ich habe ein Hauptformular (nennen wir es frmHireQuote), das ein untergeordnetes Element eines Haupt-MDI-Formulars (frmMainMDI) ist und das über ShowDialog () ein anderes Formular (frmImportContact) anzeigt, wenn auf eine Schaltfläche geklickt wird.

Wenn der Benutzer in frmImportContact auf "OK" klickt, möchte ich einige Zeichenfolgenvariablen an einige Textfelder in frmHireQuote zurückgeben.

Beachten Sie, dass es mehrere Instanzen von frmHireQuote geben kann. Es ist offensichtlich wichtig, dass ich zu der Instanz zurückkehre, die diese Instanz von frmImportContact aufgerufen hat.

Was ist die beste Methode, um dies zu tun?

Jez Clark
quelle

Antworten:

365

Erstellen Sie einige öffentliche Eigenschaften auf Unterform wie so

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

Stellen Sie dies dann in Ihrem Unterformular- OK-Klick-Handler ein

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

Dann in Ihrem frmHireQuote-Formular , wenn Sie das Unterformular öffnen

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

Wenn Sie das Unterformular abbrechen möchten, können Sie dem Formular einfach eine Schaltfläche hinzufügen und dessen DialogResult auf festlegen.Cancel Außerdem können Sie die CancelButton- Eigenschaft des Formulars auf diese Schaltfläche setzen. Dadurch kann die Escape- Taste abgebrochen werden der Form.

Richard Freund
quelle
33
Ein paar wichtige Mängel. Ein Formular, das mit ShowDialog () angezeigt wird, wird nicht entsorgt. Sie müssen hier die using- Anweisung verwenden. ShowDialog () gibt einen DialogResult-Wert zurück. Ignorieren Sie ihn nicht. Andernfalls versuchen Sie, die Dialogeigenschaften zu verwenden, wenn der Benutzer den Dialog abgebrochen hat.
Hans Passant
Prost, ich habe das erklärt.
Jez Clark
Minikritik: Set braucht Semikolon angehängt.
B. Clay Shannon
16

Normalerweise erstelle ich eine statische Methode für Formular / Dialog, die ich aufrufen kann. Dies gibt den Erfolg (OK-Taste) oder Misserfolg zusammen mit den Werten zurück, die eingegeben werden müssen.

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


 }

Und auf dem Formular:

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

Um Ihr Formular anzurufen;

public void MyEventToCallForm() {
   var result = frmMain.Execute();
   if (result.Result == DialogResult.OK) {
       myTextBox.Text = result.Field1; // or something like that
   }
}
GvS
quelle
Habe diesen Ansatz auch benutzt, funktioniert gut. Das Präfixieren der Ergebnisklasse mit frmcan (und genau das, als ich es gelesen habe) führt jedoch zu Verwirrung ...
Richard Friend
Ich habe gerade den Namen aus der Frage wiederverwendet (+ schnelles Tippen). Ich werde es in einen besseren Namen ändern.
GvS
6

Ich habe ein weiteres kleines Problem mit diesem Code gefunden ... oder zumindest war es problematisch, als ich versuchte, ihn zu implementieren.

Die Schaltflächen in frmMain geben keinen kompatiblen Wert zurück. Mit VS2010 habe ich Folgendes hinzugefügt und alles begann einwandfrei zu funktionieren.

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

Nach dem Hinzufügen der beiden Schaltflächenwerte funktionierte der Dialog hervorragend! Danke für das Beispiel, es hat wirklich geholfen.

DaveHelton
quelle
1

Ich habe nur etwas als Referenz in den Konstruktor eingefügt, damit das Unterformular seinen Wert ändern kann und das Hauptformular neue oder geänderte Objekte aus dem Unterformular abrufen kann.

SerG
quelle
0

Ich benutze MDI ziemlich oft, ich mag es viel mehr (wo es verwendet werden kann) als mehrere schwebende Formen.

Aber um das Beste daraus zu machen, müssen Sie sich mit Ihren eigenen Ereignissen auseinandersetzen. Es macht dir das Leben so viel einfacher.

Ein Skelettbeispiel.

Haben Sie Ihre eigenen Interrupt-Typen,

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

Dann dein eigener Args-Typ

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

}

Verwenden Sie dann den Delegaten in Ihrem Namespace, jedoch außerhalb einer Klasse

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

Lassen Sie den MDIparent jetzt entweder manuell oder über die GUI auf die Ereignisse der untergeordneten Formulare reagieren.

Aber mit Ihren eigenen Args können Sie dies auf eine einzige Funktion reduzieren. und Sie können Vorkehrungen treffen, um die Interrupts zu unterbrechen, gut zum Debuggen, aber auch auf andere Weise nützlich sein.

Lassen Sie einfach alle Ihre mdiparenten Ereigniscodes auf die eine Funktion verweisen.

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

Ein einfacher Schaltmechanismus reicht normalerweise aus, um Ereignisse an geeignete Formulare weiterzuleiten.

Bob
quelle
0

Wenn Sie Daten an form2von form1übergeben möchten, ohne wie neu zu übergebenform(sting "data");

Mach das in Form 1

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

in Form 2 hinzufügen

public string ReturnValue1 { get; set; }

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

Sie können den Wert auch form1so verwenden, wenn Sie etwas eintauschen möchtenform1

nur in form1

textbox.Text =form2.ReturnValue1
Matas Lesinskas
quelle
0

Zuerst müssen Sie das Attribut in form2 (untergeordnet) definieren. Sie aktualisieren dieses Attribut in form2 und auch in form1 (übergeordnet):

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

Aufruf von form2 (Kind) von form1 (Eltern):

  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
quelle
0

Ich löse ein Ereignis in dem Formular aus, in dem der Wert festgelegt ist, und abonniere dieses Ereignis in den Formularen, die sich mit der Wertänderung befassen müssen.

Edward Miller
quelle
Sie da! Können Sie Ihre Antwort etwas näher erläutern und möglicherweise ein Codebeispiel bereitstellen, um zukünftigen Benutzern zu helfen?
Jeremy Harris
0

Delegierte sind die beste Option zum Senden von Daten von einem Formular zu einem anderen.

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");
    }
}
Sagte Muhammad Idrees
quelle