因为这是一个非常大的项目,我经常需要从类中访问其他形式的对象,我首先在我的program.cs类中创建一个静态变量,类型为'MainForm',这是一个Windows窗体。
从我的DataManger.cs类中,我实例化对象'Program.MainFormObj = new MainForm()',然后调用Show方法以显示我的Form。看起来表单的Paint事件没有完成,但它会在绘制一些控件时启动。大概是因为主线程(这是所有在主线程上运行的线程)被下一个语句“占用”。我想,无论已知问题,我都会使用Application.DoEvents()来暂时解决这个问题。正如我想象的那样,它起作用,但只是在一定程度上。如果我使用像MessageBox.Show()这样的阻塞方法,我可以在后台查看完全完美的表单,但只要按“确定”,代码就会继续运行整个应用程序。
我真的被困住了。尽管在这里广泛搜索并使用谷歌我找不到一个apporpiate答案。我这样做了这个帖子:Form.Show() is not showing it's child controls但是给定的解决方案不适合我的解决方案。非常感谢任何帮助,谢谢。
答案 0 :(得分:2)
如果这是一个大项目,现在就投入时间来重构它。
在中期战胜WinForms的工作方式将比现在投入时间做得更加昂贵。
如果您对该技术有任何选择,请考虑使用WPF。 WPF有一个学习曲线,但现在可能值得投资学习。
<强>更新强>
根据您的代码示例,我发现您可能在主UI线程以外的线程上创建了一些表单。虽然这是允许的,但它会创建非常混乱的代码,因为表单只能从创建的线程更新。
使这项工作最简单的方法可能是更新HandleIncomingData
以调用主UI线程上的Show()
调用。
应该有一种方法可以通过静态方法干净地做到这一点,如下所述:
https://stackoverflow.com/a/505361/141172
但是,当我尝试这样做时,我发现SynchronizationContext
始终为空。我确定我只是错过了一步。
我能够通过滥用LoginForm
来解决问题(假设,也许是错误的,表单始终可用。如果没有,也许只为线程封送创建一个特殊的表单。)
黑客看起来像这样:
Program.MainForm = new MainForm();
try
{
MessageBox.Show("Login Success.", "Login", MessageBoxButtons.OK, MessageBoxIcon.Information);
// Abusing LoginForm's Invoke method. Code assumes LoginForm is always available.
Program.LoginForm.Invoke((MethodInvoker)delegate
{
Program.MainForm.Show();
});
}
catch (Exception Ex)
{
MessageBox.Show(Ex.ToString()); //Debuging purposes
}
顺便说一句,有一个很好的扩展方法,可以轻松地从非UI线程调用UI代码: