GUIを勉強し始めた頃に悩んだので、記録としてここに残します。
方法① サブフォームから、メインフォームの公開プロパティに値をセットする。
この場合、サブフォームがメインフォームのpublicプロパティにアクセスする必要があるので、
サブフォームがメインフォームへの参照を持つ必要があります。
※サブフォームにpublicプロパティを作って、メインフォームがアクセスしても同じ。
public class MainForm : Form
{
public string PublicProperty { get; set; }
public void ShowSubForm()
{
var form = new SubForm()
{
ParentForm = this;
};
form.Show();
}
}
public class SubForm : Form
{
public Form ParentForm { get; set; }
private void SetValueMethod()
{
ParentForm.PublicProperty = "テキスト";
}
}
方法② データ受け渡し用のクラスを介して受け渡しする。
この方法なら、メインフォームとサブフォームが互いに参照することなく、データを受け渡し出来ます。
public static class DataClass
{
public static string StringValue { get; set; }
}
public class MainForm : Form
{
private string PrivateStringProperty { get; set; }
public void GetValueMethod()
{
PrivateStringProperty = DataClass.StringValue;
}
}
public class SubForm : Form
{
public void SetValue()
{
DataClass.StringValue = "テキスト";
}
}
方法③ イベントを使って渡す。
イベントを使う方法は、方法④ イベントを使って、DBを仲介してデータを受け渡しする時に便利。
public class MainForm : Form
{
private string PrivateStringProperty { get; set; }
public void ShowSubForm()
{
var form = new SubForm()
{
ParentForm = this;
};
form.DataPassEvent += SubForm_DataPassEvnet;
form.Show();
}
private void SubForm_DataPassEvnet(object sender, DataPassEventArgs e)
{
PrivateStringProperty = e.StringData;
}
}
public class SubForm : Form
{
public delegate void DataEventHandler(DataPassEventArgs e);
//このイベントをメインフォームでListenする。
public event DataEventHandler DataPassEvent;
private string StringDate;
public void SetValue()
{
//ここでデータを加工したりする処理をして・・・
//空白でない時だけ、イベントを起こしたりも出来る。
if(!string.IsNullOrWhiteSpace(StringDate))
{
DataPassEvent?.Invoke(new DataPassEventArgs(StringData));
}
}
}
public class DataPassEventArgs : EventArgs
{
public string StringData { get; set; }
public DataPassEventArgs(string data)
{
StringData = data;
}
}
方法④ イベントを使って、DBを仲介してデータを受け渡しする。
①サブフォームでDB更新 → ②DB更新した事をイベントとして通知 → ③メインフォームがDBのデータを参照
という流れ。
今回の場合は、データはDBにあるので、独自のEventArgsで渡す必要はありません。
必要であれば、更新したレコードの主キー等、渡す必要があるデータを渡すEventArgsを作ります。
public class MainForm : Form
{
public void ShowSubForm()
{
var form = new SubForm();
form.DatabaseUpdateCompleted += SubForm_DatabaseUpdateCompleted;
form.Show();
}
private void SubForm_DatabaseUpdateCompleted(object sender, EventArgs e)
{
//データベースからデータを取得する処理。
}
}
public class SubForm : Form
{
public event EventHandler DatabaseUpdateCompleted;
public void UpdateDatabase()
{
//ここでデータベースにレコードをInsertしたりUpdateしたりして・・・
//その後、イベント起動。
DatabaseUpdateCompleted?.Invoke(null, new EventArgs());
}
}
方法⑤ データ受け渡し用クラスで、データ変更イベントを起動して他のフォームに変更を通知する。
①サブフォームでDataClassのデータ更新 → ②DataClassがデータ変更イベントを起動 → ③イベントをListenしているメインフォームがデータを受け取る。
という流れ。
namespace Test
{
public class MainForm : Form
{
static void Main(string[] args)
{
Application.Run(new MainForm());
}
public MainForm()
{
//データ管理用クラスの、データ変更イベントをListenする。
DataClass.DataPassEvent += DataClass_DataPassEvent;
//サブフォーム内に実装した、データを変更するメソッドを呼び出す。
//下記メソッドはどのクラスから呼び出してもいいが、今回は2つしかクラスがないので、このクラスで呼び出す。
new SubForm().Method();
}
private static void DataClass_DataPassEvent(DataChangeEventArgs e)
{
//データ変更前後の値を表示する。
//メッセージBOXは4回表示され、表示結果は以下
//------------------------------------------
//①変更前は で 変更後は あいうえお
//②変更前は あいうえお で 変更後は かきくけこ
//③変更前は かきくけこ で 変更後は さしすせそ
//④変更前は さしすせそ で 変更後は たちつてと
//------------------------------------------
MessageBox.Show($"変更前は { e.OldStringData } で 変更後は { e.NewStringData } ");
}
}
public class SubForm : Form
{
//データ管理用クラスのデータを変更する。
public void Method()
{
DataClass.StringValue = "あいうえお";
DataClass.StringValue = "かきくけこ";
DataClass.StringValue = "さしすせそ";
DataClass.StringValue = "たちつてと";
}
}
//データ管理用クラス
public static class DataClass
{
public delegate void DataEventHandler(DataChangeEventArgs e);
//このイベントをメインフォームとサブフォームでListenする。
public static event DataEventHandler DataPassEvent;
private static string oldValue;
private static string newValue;
public static string StringValue
{
get { return newValue; }
set
{
//データ変更前後の値が違っていれば・・・
if (oldValue != value)
{
//元々あった値をoldValueに退避
oldValue = newValue;
//newValueにセットし・・・
newValue = value;
//データ変更イベントを起動する。
DataPassEvent?.Invoke(new DataChangeEventArgs(oldValue, newValue));
};
}
}
}
//変更前後の値を渡す為のEventArgs
public class DataChangeEventArgs : EventArgs
{
public string OldStringData { get; set; }
public string NewStringData { get; set; }
public DataChangeEventArgs(string oldData, string newData)
{
OldStringData = oldData;
NewStringData = newData;
}
}
}