从C#中的另一个表单听主表格中的事件

时间:2009-03-04 12:22:25

标签: c# .net winforms event-handling

我有一个具有主窗体的应用程序,并使用事件处理程序处理传入的数据并反映主窗体上各种控件的更改。这很好。

我在应用程序中还有另一个表单。在任何给定时间都可以运行第二种形式的多个实例。

我想要做的是让第二个表单的每个实例都监听主表单中的事件处理程序,并更新其第二个表单实例的控件。

我该怎么做?

这是一些示例代码。我想从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();
    }
}

3 个答案:

答案 0 :(得分:5)

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
  }

答案 1 :(得分:2)

考虑使用松耦合事件。这将允许您以一种他们永远不必直接彼此了解的方式来结合这些类。 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/作为示例。

答案 2 :(得分:0)

我猜你可以让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 += .....
}