メインのフォーム(frmHireQuoteと呼びましょう)がメインのMDIフォーム(frmMainMDI)の子であり、ボタンがクリックされるとShowDialog()を介して別のフォーム(frmImportContact)を表示します。
ユーザーがfrmImportContactで[OK]をクリックすると、frmHireQuoteのテキストボックスに文字列変数をいくつか渡します。
FrmHireQuoteのインスタンスが複数存在する可能性があることに注意してください。frmImportContactのこのインスタンスを呼び出したインスタンスに戻ることが明らかに重要です。
これを行う最良の方法は何ですか?
以下のようにサブフォームにパブリックプロパティを作成します。
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 を設定するだけです。 Cancel
にすることもできますし、フォームの CancelButton プロパティを上記のボタンに設定することもできます。これにより、エスケープキーを使用してフォームからキャンセルすることができます。
私は通常、フォーム/ダイアログ上に静的メソッドを作成します。それを呼び出すことができます。これは成功(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
}
}
このコードに関する別の小さな問題を見つけました...または少なくともそれを実装しようとしたときに問題がありました。
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つのボタン値を追加した後、ダイアログは素晴らしく機能しました。例をありがとう、それは本当に役に立ちました。
参照によってコンストラクタに何かを入れただけなので、サブフォームはその値を変更でき、メインフォームはサブフォームから新しいオブジェクトまたは変更されたオブジェクトを取得できます。
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
最初にform2(child)で属性を定義しなければなりません。あなたはform2(そしてparent1)からもこの属性を更新するでしょう:
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(親)からform2(子)を呼び出す:
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);
}
値を設定するフォームでイベントを発生させ、値の変更を処理する必要があるフォームでそのイベントを購読します。
デリゲートは、あるフォームから別のフォームにデータを送信するための最良の選択肢です。
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");
}
}
私は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に子フォームのイベントに応答させます。
しかし、あなたのowr 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);
単純な切り替え機構は通常、イベントを適切なフォームに渡すのに十分です。
必要なのは、次のように「d」形式を追加することだけです。
private void NewAdmin_Form3_Load_1(object sender, EventArgs e)
{
DateTime today = DateTime.Today;
DateTime DateOnly = today.Date;
DateTime answer = DateOnly.AddDays(90);
ExitDateAdmin.Text = answer.Date.ToString("d");
}