如何避免将活动提升到封闭的形式?

时间:2010-04-20 14:17:52

标签: c# winforms events delegates

我无法处理将事件提升到封闭状态并希望得到一些帮助的情况。

场景(请参阅下面的代码以供参考):

  1. Form1打开Form2
  2. Form1订阅Form2上的活动(让我们称之为活动FormAction
  3. Form1已关闭且Form2仍然有效
  4. Form2提出FormAction事件
  5. Form1.form2_FormAction中,为什么this会返回对Form1的引用,但button1.Parent会返回null?他们不应该都返回相同的参考文献吗?

    如果我们要省略第3步,则thisbutton1.Parent都会返回相同的引用。

    这是我正在使用的代码......

    Form1中:

    public partial class Form1 : Form
    {
        public Form1 ()
        {
            InitializeComponent();
        }
    
        private void button1_Click ( object sender , EventArgs e )
        {
            // Create instance of Form2 and subscribe to the FormAction event
            var form2 = new Form2();
            form2.FormAction += form2_FormAction;
            form2.Show();
        }
    
        private void form2_FormAction ( object o )
        {
            // Always returns reference to Form1
            var form = this;
    
            // If Form1 is open, button1.Parent is equal to form/this
            // If Form1 is closed, button1.Parent is null
            var parent = button1.Parent;
        }
    }
    

    窗体2:

    public partial class Form2 : Form
    {
        public Form2 ()
        {
            InitializeComponent();
        }
    
        public delegate void FormActionHandler ( object o );
        public event FormActionHandler FormAction = delegate { };
    
        private void button1_Click ( object sender , EventArgs e )
        {
            FormAction( "Button clicked." );
        }
    }
    

    理想情况下,我希望避免将事件发送到已关闭/处理的表单(我不确定是否可行),或者在调用者中找到一种干净的处理方法(在本例中为Form1)。

    感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

当您关闭form1时,您应该取消订阅活动:

form2.FormAction -= form2_FormAction;

答案 1 :(得分:3)

一个简单的解决方案是使用覆盖所有者的覆盖来显示您的Form2实例:

form2.Show(this);

这将确保在关闭form1时关闭form2。无论如何,在多表单应用程序中通常都是很好的做法,因此您没有任何无主形式的表单。

更新:事件模型只是处理表单之间通信的一种方式。在你的情况下,它不是真的合适,因为接收事件的表单可以关闭,而不会提升事件意识到它。

另一种方法是使用构造函数编写Form2,该构造函数包含Form1的实例作为参数(可以保存为表单级成员,如_Receiver或其他东西)。在检查是否已经处理了_Receiver之后,Form2将调用Form1中定义的方法而不是引发事件:

if (!_Receiver.IsDisposed)
{
    _Receiver.SomeMethod("some method");
}

如果您的Form1实例仍然存在,则会调用其方法;如果它被关闭并处理掉,它的方法就不会被调用。由于Form2仍然存在,您还可以将_Receiver变为公共属性,并随时将其“所有者”设置为其他Form1。