C#のフォームから値を返す方法は?


185

ボタンがクリックされたときにShowDialog()を介して別のフォーム(frmImportContact)を表示するメインMDIフォーム(frmMainMDI)の子であるメインフォーム(frmHireQuoteとしましょう)があります。

ユーザーがfrmImportContactの[OK]をクリックすると、frmHireQuoteのいくつかのテキストボックスにいくつかの文字列変数を渡したいと思います。

frmHireQuoteの複数のインスタンスが存在する可能性があることに注意してください。frmImportContactのこのインスタンスを呼び出したインスタンスに戻ることが重要です。

これを行う最良の方法は何ですか?

回答:


367

そのようなあなたのサブフォームにいくつかのパブリックプロパティを作成します

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

次に、これをサブフォームの OKボタンのクリックハンドラ内に設定します

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

次に、frmHireQuoteフォームで、サブフォームを開くと

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

さらに、サブフォームをキャンセルしたい場合は、ボタンをフォームに追加して、そのDialogResultをに設定し、フォームCancelCancelButtonプロパティをボタンに設定することもできます。これにより、エスケープキーでキャンセルできます。フォームの。


33
いくつかの重要な欠陥。ShowDialog()で表示されるフォームは破棄されません。ここでは、usingステートメントを使用する必要があります。ShowDialog()はDialogResult値を返します。無視しないでください。そうしないと、ユーザーがダイアログをキャンセルしたときにダイアログプロパティを使用しようとします。
ハンスパッサント

乾杯、私はこれを説明しました。
Jez Clark

ミニ批評:セットにはセミコロンを追加する必要があります。
B.クレイシャノン

16

私は通常、フォーム/ダイアログに呼び出すことができる静的メソッドを作成します。これは、入力が必要な値とともに、成功(OKボタン)または失敗を返します。

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


 }

そしてフォーム上:

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

フォームを呼び出すには、

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

このアプローチも使用しており、うまく機能します。ただし、結果クラスの前にfrmcanを付けると(そして、私がそれを読んだときだけに)、混乱を招きます...
Richard Friend

質問の名前を再利用しました(+高速入力)。わかりやすい名前に変更します。
GvS 2011年

6

このコードに別の小さな問題が見つかりました...少なくとも、実装しようとしたときに問題がありました。

frmMainのボタンは互換性のある値を返しません。VS2010を使用して、以下を追加すると、すべてが正常に機能し始めました。

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

2つのボタンの値を追加した後、ダイアログはうまくいきました!例をありがとう、それは本当に役に立ちました。


1

参照によって何かをコンストラクターに入れただけなので、サブフォームはその値を変更でき、メインフォームはサブフォームから新しいオブジェクトまたは変更されたオブジェクトを取得できます。


0

私はMDIをかなり頻繁に使用していますが、複数のフローティングフォームよりも(使用できる場所で)ずっと気に入っています。

しかし、それを最大限に活用するには、自分のイベントをしっかりと把握する必要があります。それはあなたにとって人生をとても簡単にします。

骨格の例。

独自の中断タイプがあります。

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

次に、独自の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; }

}

次に、名前空間内で、クラスの外でデリゲートを使用します

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

次に、手動またはGUIを使用して、MDIparentが子フォームのイベントに応答するようにします。

しかし、独自のArgsを使用すると、これを単一の関数に減らすことができます。そして、あなたは中断に干渉する準備をすることができ、デバッグには良いですが、他の点でも有用であるかもしれません。

mdiparentイベントコードのすべてに1つの関数を指定させるだけです。

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

通常、イベントを適切なフォームに渡すには、単純な切り替えメカニズムで十分です。


0

あなたはにデータを渡す場合form2から、form1新しいように通過することなくform(sting "data");

そのようにしてください1

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

フォーム2に追加

public string ReturnValue1 { get; set; }

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

また、form1何かを入れ替えたい場合は、このように値を使用できますform1

ちょうどform1

textbox.Text =form2.ReturnValue1

0

最初にform2(child)で属性を定義する必要があります。form2でこの属性を更新し、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";
 }

form1(parent)からform2(child)を呼び出す:

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

0

値を設定するフォームでイベントを発生させ、値の変更を処理する必要があるフォームでそのイベントをサブスクライブします。


ちょっと、そこ!回答についてもう少し詳しく説明して、将来のユーザーを支援するためのコードサンプルを提供できますか?
ジェレミーハリス

0

デリゲートは、あるフォームから別のフォームにデータを送信するための最良のオプションです。

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");
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.