Jak zwrócić wartość z formularza w C #?

185

Mam główny formularz (nazwijmy go frmHireQuote), który jest dzieckiem głównego formularza MDI (frmMainMDI), który pokazuje inny formularz (frmImportContact) za pośrednictwem ShowDialog () po kliknięciu przycisku.

Gdy użytkownik kliknie „OK” na frmImportContact, chcę przekazać kilka zmiennych łańcuchowych z powrotem do niektórych pól tekstowych na frmHireQuote.

Zauważ, że może istnieć wiele instancji frmHireQuote, to oczywiście ważne, że wrócę do instancji, która wywołała tę instancję frmImportContact.

Jaka jest najlepsza metoda tego?

Jez Clark
źródło

Odpowiedzi:

367

Tworzenie niektóre właściwości publiczne w sub-forma podobnie jak

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

następnie ustaw to w swoim formularzu obsługi przycisku OK

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

Następnie w formularzu frmHireQuote po otwarciu podformularza

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

Dodatkowo, jeśli chcesz zrezygnować z sub-formularza można po prostu dodać przycisk do formularza i ustawić jego DialogResult aby Cancelmożna także ustawić CancelButton własność postaci do wspomnianego przycisku - to pozwoli klawisz Esc, aby anulować formularza.

Richard Friend
źródło
33
Kilka ważnych wad. Formularz wyświetlany za pomocą ShowDialog () nie jest usuwany. Musisz użyć instrukcji using tutaj. ShowDialog () zwraca wartość DialogResult, nie ignoruj ​​jej, albo spróbujesz użyć właściwości okna dialogowego, gdy użytkownik anuluje okno dialogowe.
Hans Passant,
Pozdrawiam, rozliczałem się z tego.
Jez Clark,
Mini-krytyka: zestaw wymaga dołączonego średnika.
B. Clay Shannon
16

Zwykle tworzę statyczną metodę w formularzu / oknie dialogowym, którą mogę wywołać. Zwraca sukces (przycisk OK) lub niepowodzenie, wraz z wartościami, które należy wypełnić.

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


 }

I na formularzu:

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

Aby zadzwonić do formularza;

public void MyEventToCallForm() {
   var result = frmMain.Execute();
   if (result.Result == DialogResult.OK) {
       myTextBox.Text = result.Field1; // or something like that
   }
}
GvS
źródło
Użyłem również tego podejścia, działa dobrze. Jednak poprzedzenie klasy wynikowej puszką frm(i właśnie to zrobiłem, gdy ją przeczytałem) prowadzi do zamieszania ...
Richard Friend
Właśnie użyłem nazwy z pytania (+ szybkie pisanie). Zamienię to na lepsze imię.
GvS,
6

Znalazłem inny mały problem z tym kodem ... a przynajmniej był problematyczny, gdy próbowałem go zaimplementować.

Przyciski w frmMain nie zwracają kompatybilnej wartości, używając VS2010 dodałem następujące i wszystko zaczęło działać dobrze.

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

Po dodaniu dwóch wartości przycisków okno dialogowe działało świetnie! Dzięki za przykład, to naprawdę pomogło.

DaveHelton
źródło
1

Po prostu wstawiłem do konstruktora coś przez odniesienie, aby podformularz mógł zmienić swoją wartość, a główna forma mogła uzyskać nowy lub zmodyfikowany obiekt z podformularza.

SerG
źródło
0

Używam MDI całkiem sporo, podoba mi się to bardziej (tam, gdzie można go używać) niż wiele form pływających.

Ale aby czerpać z tego jak najwięcej, musisz poradzić sobie z własnymi wydarzeniami. Ułatwia ci to życie.

Przykład szkieletu.

Posiadaj własne typy przerwań,

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

Następnie twój własny typ 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; }

}

Następnie użyj delegata w przestrzeni nazw, ale poza klasą

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

Teraz albo ręcznie, albo za pomocą GUI, poproś MDIparent o reakcję na formularze potomne.

Ale dzięki swoim argumentom Owr możesz zredukować to do jednej funkcji. i możesz mieć możliwość przerywania przerwań, co jest dobre do debugowania, ale może być także przydatne na inne sposoby.

Wystarczy, że wszystkie kody zdarzeń mdiparent wskazują na jedną funkcję,

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

Zwykły mechanizm przełączania zwykle wystarcza, aby przekazać zdarzenia do odpowiednich formularzy.

Pion
źródło
0

Jeśli chcesz przekazać dane form2z form1bez przekazywania jak noweform(sting "data");

Zrób tak w formularzu 1

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

w formularzu 2 dodaj

public string ReturnValue1 { get; set; }

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

Możesz także użyć wartości w form1ten sposób, jeśli chcesz coś zamienićform1

tylko w formie 1

textbox.Text =form2.ReturnValue1
Matas Lesinskas
źródło
0

Najpierw musisz zdefiniować atrybut w formularzu 2 (dziecko), zaktualizujesz ten atrybut w formularzu 2, a także z formularza 1 (rodzic):

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

Wywołanie formularza 2 (dziecko) z formularza 1 (rodzic):

  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
źródło
0

Zgłaszam zdarzenie w formularzu określającym wartość i subskrybuję to zdarzenie w formularzu (formularzach), które muszą poradzić sobie ze zmianą wartości.

Edward Miller
źródło
No hej! Czy możesz uszczegółowić swoją odpowiedź i ewentualnie podać próbkę kodu, aby pomóc przyszłym użytkownikom?
Jeremy Harris,
0

delegaci są najlepszą opcją do przesyłania danych z jednego formularza do drugiego.

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
źródło