Como retornar um valor de um formulário em c #?

185

Eu tenho um formulário principal (vamos chamá-lo de frmHireQuote) que é filho de um formulário MDI principal (frmMainMDI), que mostra outro formulário (frmImportContact) via ShowDialog () quando um botão é clicado.

Quando o usuário clica em 'OK' em frmImportContact, desejo passar algumas variáveis ​​de string de volta para algumas caixas de texto em frmHireQuote.

Observe que pode haver várias instâncias do frmHireQuote, é obviamente importante que eu volte à instância que chamou essa instância de frmImportContact.

Qual é o melhor método para fazer isso?

Jez Clark
fonte

Respostas:

367

Crie algumas propriedades públicas no seu sub-formulário, assim:

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

em seguida, defina isso dentro do seu sub-formulário , clique em OK, manipulador de cliques

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

Em seu formulário frmHireQuote , quando você abre o sub-formulário

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

Adicionalmente, se você deseja cancelar fora do sub-forma você pode simplesmente adicionar um botão para o formulário e defina sua DialogResult para Cancele você também pode definir o CancelButton propriedade do formulário para o referido botão - o que irá permitir que a chave de escape para cancelar do formulário.

Richard Friend
fonte
33
Um par de falhas importantes. Um formulário exibido com ShowDialog () não é descartado. Você deve usar a instrução using aqui. ShowDialog () retorna um valor DialogResult, não o ignore ou você tentará usar as propriedades da caixa de diálogo quando o usuário cancelou a caixa de diálogo.
Hans Passant
Saúde, eu expliquei isso.
precisa
Mini-crítica: o conjunto precisa de um ponto e vírgula anexado.
B. Clay Shannon
16

Normalmente, crio um método estático no formulário / caixa de diálogo que posso chamar. Isso retorna o sucesso (botão OK) ou falha, junto com os valores que precisam ser preenchidos.

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


 }

E no formulário:

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

Para chamar seu formulário;

public void MyEventToCallForm() {
   var result = frmMain.Execute();
   if (result.Result == DialogResult.OK) {
       myTextBox.Text = result.Field1; // or something like that
   }
}
GvS
fonte
Também utilizaram essa abordagem, funciona bem. No entanto prefixo da classe resultado com frmlata (e apenas fiz quando eu lê-lo) levam a confusão ...
Richard Friend
Acabei de reutilizar o nome da pergunta (+ digitação rápida). Vou mudar para um nome melhor.
GvS 8/03/11
6

Encontrei outro pequeno problema com esse código ... ou pelo menos era problemático quando tentei implementá-lo.

Os botões no frmMain não retornam um valor compatível, usando o VS2010 eu adicionei o seguinte e tudo começou a funcionar bem.

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

Depois de adicionar os dois valores do botão, a caixa de diálogo funcionou muito bem! Obrigado pelo exemplo, realmente ajudou.

DaveHelton
fonte
1

Acabei de colocar no construtor algo por referência, para que o subformulário possa alterar seu valor e a forma principal possa obter objetos novos ou modificados do subformulário.

SerG
fonte
0

Eu uso muito o MDI, gosto muito mais (onde pode ser usado) do que vários formulários flutuantes.

Mas, para tirar o melhor proveito, você precisa se familiarizar com seus próprios eventos. Isso torna a vida muito mais fácil para você.

Um exemplo esquelético.

Tenha seus próprios tipos de interrupção,

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

Então seu próprio tipo de 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; }

}

Em seguida, use o delegado dentro do seu espaço para nome, mas fora de uma classe

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

Agora, manualmente ou usando a GUI, peça ao MDIparent que responda aos eventos dos formulários filhos.

Mas com o seu proprietário Args, você pode reduzir isso para uma única função. e você pode ter provisão para interromper as interrupções, bom para depuração, mas também pode ser útil de outras maneiras.

Basta ter todos os seus códigos de evento mdiparent apontados para a única função,

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

Um mecanismo simples de troca geralmente é suficiente para passar eventos para os formulários apropriados.

Prumo
fonte
0

Se você deseja passar dados form2de form1sem passar como novosform(sting "data");

Faça assim no formulário 1

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

no formulário 2 adicione

public string ReturnValue1 { get; set; }

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

Além disso, você pode usar um valor form1como este se quiser trocar algoform1

apenas no form1

textbox.Text =form2.ReturnValue1
Matas Lesinskas
fonte
0

Primeiro, você precisa definir o atributo no formulário2 (filho); você atualizará esse atributo no formulário2 e também no formulário1 (pai):

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

Chamada do formulário2 (filho) do formulário1 (pai):

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

Eu levanto um evento no formulário que define o valor e assino esse evento nos formulários que precisam lidar com a alteração de valor.

Edward Miller
fonte
Olá! Você pode elaborar um pouco mais de sua resposta e possivelmente fornecer um exemplo de código para ajudar futuros usuários?
Jeremy Harris
0

delegados são a melhor opção para enviar dados de um formulário para outro.

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
fonte