C#の別のフォームからメインフォームのイベントをリッスンする
-
03-07-2019 - |
質問
メインフォームがあり、イベントハンドラーを使用して着信データを処理し、メインフォームのさまざまなコントロールに変更を反映するアプリケーションがあります。これは正常に機能します。
アプリケーションにも別のフォームがあります。この2番目のフォームのインスタンスは、いつでも複数実行できます。
やりたいのは、この2番目のフォームの各インスタンスがメインフォームのイベントハンドラーをリッスンし、2番目のフォームのインスタンスのコントロールを更新することです。
どうすればいいですか?
サンプルコードを次に示します。 the_timer_Tickイベントハンドラーから情報を取得して、SecondaryFormの各インスタンスを更新します。
public partial class Form1 : Form
{
Timer the_timer = new Timer();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
the_timer.Tick += new EventHandler(the_timer_Tick);
the_timer.Interval = 2000;
the_timer.Enabled = true;
}
void the_timer_Tick(object sender, EventArgs e)
{
// I would like code in here to update all instances of SecondaryForm
// that happen to be open now.
MessageBox.Show("Timer ticked");
}
private void stop_timer_button_Click(object sender, EventArgs e)
{
the_timer.Enabled = false;
}
private void start_form_button_Click(object sender, EventArgs e)
{
SecondaryForm new_form = new SecondaryForm();
new_form.Show();
}
}
解決
class SecondForm
{
private FirstForm firstForm;
public SecondForm()
{
InitializeComponent();
// this means unregistering on form closing, uncomment if is necessary (anonymous delegate)
//this.Form_Closing += delegate { firstForm.SomeEvent -= SecondForm_SomeMethod; };
}
public SecondaryForm(FirstForm form) : this()
{
this.firstForm = form;
firstForm.Timer.Tick += new EventHandler(Timer_Tick);
}
// make it public in case of external event handlers registration
private void Timer_Tick(object sender, EventArgs e)
{
// now you can access firstForm or it's timer here
}
}
class FirstForm
{
public Timer Timer
{
get
{
return this.the_timerl
}
}
public FirstForm()
{
InitializeComponent();
}
private void Button_Click(object sender, EventArgs e)
{
new SecondForm(this).ShowDialog(); // in case of internal event handlers registration (in constructor)
// or
SecondForm secondForm = new SecondForm(this);
the_timer.Tick += new EventHandler(secondForm.Timer_tick); // that method must be public
}
他のヒント
疎結合イベントの使用を検討してください。これにより、クラスを相互に直接認識する必要がなくなるような方法でクラスを結合できます。 Unityアプリケーションブロックには、 EventBroker と呼ばれる拡張機能が付属しており、これにより、シンプル。
砂糖を少し舐めます:
public static class EVENTS
{
public const string UPDATE_TICKED = "event://Form1/Ticked";
}
public partial class Form1 : Form
{
[Publishes(EVENTS.UPDATE_TICKED)]
public event EventHandler Ticked;
void the_timer_Tick(object sender, EventArgs e)
{
// I would like code in here to update all instances of SecondaryForm
// that happen to be open now.
MessageBox.Show("Timer ticked");
OnTicked();
}
protected virtual void OnTicked()
{
if (Ticked == null) return;
Ticked(this, e);
}
}
public partial class SecondaryForm : Form
{
[SubscribesTo(EVENTS.UPDATE_TICKED)]
private void Form1_Ticked(object sender, EventHandler e)
{
// code to handle tick in SecondaryForm
}
}
Unityを使用してこれらのクラスの両方を構築すると、自動的に相互に接続されます。
更新
新しいソリューションでは、メッセージバスを使用して疎結合イベントを処理します。 http://masstransit-project.com/ または例としてhttp://nimbusapi.github.io/ 。
SecondaryFormがコンストラクターで親フォームを取り、コンストラクターにイベントハンドラーを追加できるようにすると思います。
private void start_form_button_Click(object sender, EventArgs e)
{
SecondaryForm new_form = new SecondaryForm(this);
new_form.Show();
}
SecondaryForm.cs内:
public SecondaryForm(ISomeView parentView)
{
parentView.SomeEvent += .....
}
所属していません StackOverflow