希望我只是想念一些明显的东西,但是我正在努力摆脱负载和
Windows Forms中显示事件之间的差异。
传统上,我只使用Load(或者实际上是OnLoad,因为我认为覆盖一个方法比依靠设计者来自己挂起一个事件更清洁),因为这是所有版本的.NET都可用的。使用.NET 2.0引入了显示事件。
现在,如果您在MSDN文档中看到这些描述(“Load:在第一次显示表单之前发生”,“显示:首次显示表单时发生”),这听起来像加载事件应该发生,那么表单应该变得可见,那么所显示的事件应该发生;两者的结合使得您可以在表单之前和之后执行一些任务。有意义吗?
然而,实验表明,显示的事件总是发生在Load事件之前,每当我尝试(并且都发生在窗体变得可见之前)。然而,当我发现一个关于这些事件被触发的顺序的页面的时候,我总是列出它们首先列出的Load事件。
我只是疯了,还是我错过了什么? (如果他们确实发生在同一时间,那么为什么显示的事件首先被添加了?)
(我现在的解决办法是在表单之前和之后做一些事情是使用OnLoad进行“显示之前”的东西,并为“后显示”的东西开始一个短时间的单次计时器,哪个工作正常可靠,但是这有点丑,我希望有一个更清洁的解决方案,但它看起来像显示的事件不是这样。)
避免使用MessageBox.Show()来调试这个。它泵送消息循环,扰乱事件的正常流动。 Load事件由Windows发送WM_SHOWWINDOW消息触发,就在窗口可见之前。没有Windows通知,“您的窗口现在完全显示”,所以WF设计师想出了一个技巧来生成显示事件。他们使用Control.BeginInvoke(),一旦程序再次空闲并重新进入消息循环,就可以确保OnShown()方法被调用。
这个技巧有很多其他用途,特别是当你必须延迟一个事件开始的代码的执行时。但是,在您的情况下,它会因为使用MessageBox.Show()而分崩离析。它的消息循环将分派使用BeginInvoke()注册的委托,导致显示事件在窗口显示之前运行。
除了MessageBox之外,还有很多其他方法可以进行诊断。 Debug.Print()和Console.WriteLine()方便,它们的输出到Visual Studio Output Window,而不会对正常事件触发序列造成任何不利影响。一个简单的breakpoint也可以做奇迹。