设置表单的MdiParent属性会中断/阻止其已显示的事件被触发

use*_*775 2 c# events mdi winforms

所以,我一直在通过stackoverflow和其他互联网论坛和知识库搜索相似的主题,但到目前为止,我没有运气试图解决这个问题,我一直在努力整整一周.这是代码:

    private void matrículasToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Form1 form1 = new Form1();
        form1.Show();
        form1.MdiParent = this; // this == the main form of the aplication, wich has IsMdiParent property set to true.
    }
Run Code Online (Sandbox Code Playgroud)

如果我取出"form1.MdiParent = this",form1的显示事件将正常触发,执行其所有处理程序的内容,但如果我让它在那里,显示的form1事件将不会触发(我确实设置了breakpoits,none他们被触发了).

奇怪的是,如果我使用Load事件而不是显示,一切正常,但我有点害怕交换显示负载会破坏一些东西:(.

Sri*_*vel 5

试试这个代码

 Form1 form1 = new Form1();
 //Subscribe event here
 form1.MdiParent = this;
 form1.Show();
Run Code Online (Sandbox Code Playgroud)

这适合我

我不知道为什么你的代码不起作用,一旦我得到答案,我会回来的.

编辑:我现在有了答案.

ISynchronizationInvoke's成员(InvokeBeginInvoke)按Control类实现如下.

  1. 获取创建窗口的Thread的上下文.
  2. 使用生成新窗口messageId RegisterWindowMessage
  3. 封装我们作为参数传递的委托,ThreadMethodEntry将其添加到控件的内部Queue
  4. 使用message返回的messageId将消息发布到线程的队列RegisterWindowMessagePostMessage
  5. 句柄WndProc侦听messageId然后对队列进行排队ThreadMethodEntry并调用委托.

这里出了什么问题?

Form1 form1 = new Form1(); form1.Show(); form1.MdiParent = this;

Form.Show以某种方式导致对OnLoad方法的调用,即OnShown使用异步调用的地方BeginInvoke

if (base.IsHandleCreated)
{
    base.BeginInvoke(new MethodInvoker(this.CallShownEvent));//reflected code
}
Run Code Online (Sandbox Code Playgroud)

因此,在发布WindowMessage收到之前,您设置了form1.MdiParent = this;哪个依次强制控件到Destroy它的句柄和ReCreate新句柄.

DestroyHandle方法通过使用PeekMessage函数获取已发布的消息来吞下已发布的消息,然后枚举所有元素Queue并将其状态设置为已完成,而不调用委托但将其标记为要抛出ObjectDisposedException.

Form1 form1 = new Form1();
form1.Show();
Action del = () =>
{
    Console.WriteLine("This will never be called");//our custom delegates too fails to be invoked
};
var res = form1.BeginInvoke(del);
//after some more code
form1.EndInvoke(res);//throws `ObjectDisposedException` which was marked previously
form1.MdiParent = this;
Run Code Online (Sandbox Code Playgroud)

投掷ObjectDisposedException("Control")实际上是误导不是吗?

注意:您可以使用Application.DoEvents();之前轻松解决此问题,form1.MdiParent = this;因为它会DoEvents立即处理所有待处理的消息