因为这是一个相当大的项目,而且我经常需要从类中访问其他形式的对象,所以我首先在我的 program.cs 类中创建一个“MainForm”类型的静态变量,它是一个 Windows 窗体。
在我的 DataManger.cs 类中,我实例化对象“Program.MainFormObj = new MainForm()”,然后调用 Show 方法以显示我的表单。看起来窗体的 Paint 事件尚未完成,但它确实在绘制某些控件时开始。大概是因为主线程(这一切都在主线程上运行)被下一条语句“占用”。我想,无论已知问题如何,我都会使用 Application.DoEvents() 来暂时解决这个问题。正如我想象的那样,它确实有效,但只是在一定程度上有效。如果我放置像 MessageBox.Show() 这样的阻塞方法,我可以在后台查看完全完美的表单,但是一旦我按“确定”并且代码继续运行,整个应用程序就会退出。
我真的被困住了。尽管在这里和使用谷歌进行了一些广泛的搜索,但我找不到合适的答案。我在这个线程中执行了此操作:Form.Show() is not showing it's child controls但给定的解决方案不适合我的解决方案。非常感谢任何帮助,谢谢。
最佳答案
如果这是一个大型项目,请立即投入时间来重构它。
- 考虑 MVC 模式。您可以do what with WinForms ,而不仅仅是更新的 UI 技术。
- 如果您不选择 WinForms,至少将 UI 和数据分开(Data Binding 是您的 friend )。
- 当不同的表单共享通用功能时,构建可重用的组件。
从中期来看,与 WinForms 的工作方式作斗争要比现在投入时间去做正确的事情要昂贵得多。
如果您对技术有任何选择,请考虑 WPF。 WPF 有一个学习曲线,但现在很值得投资于学习。
更新
根据您的代码示例,我发现您可能在主 UI 线程以外的线程上创建一些表单。虽然这是允许的,但它会产生非常困惑的代码,因为表单只能从创建它们的线程进行更新。
要实现此功能,最简单的方法可能是更新 HandleIncomingData
以同时调用主 UI 线程上的 Show()
调用。
应该有一种方法可以通过静态方法干净地做到这一点,概述如下:
https://stackoverflow.com/a/505361/141172
但是,当我尝试时,我发现 SynchronizationContext
始终为 null。我确信我只是错过了一步。
我能够通过滥用LoginForm
来使事情正常工作(假设,也许是错误的,该表单始终可用。如果不是,也许创建一个专门用于线程编码(marshal)的特殊表单)。
黑客看起来像这样:
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 代码:
关于c# - 当我显示新表单时,控件呈白色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11320859/