C# 显示新窗体时控件为白色
因为这是一个相当大的项目,我经常需要从一个类中访问其他形式的对象,所以我首先在我的program.cs类中创建一个类型为“MainForm”的静态变量,它是一个Windows窗体 在DataManger.cs类中,我实例化对象“Program.MainFormObj=newmainform()”,然后调用Show方法以显示我的表单。看起来表单的绘制事件还没有完成,但它确实在绘制一些控件时启动。大概是因为主线程(这都在一个主线程上运行)被下一条语句“占用”。我想,不管已知的问题如何,我都会使用Application.DoEvents()暂时解决这个问题。正如我想象的那样,它起了作用,但只在一定程度上起了作用。如果我使用MessageBox.Show()之类的阻塞方法,我可以在后台查看我完全完美的表单,但只要我按下“OK”,代码就会继续运行,整个应用程序就会退出C# 显示新窗体时控件为白色,c#,.net,forms,controls,paint,C#,.net,Forms,Controls,Paint,因为这是一个相当大的项目,我经常需要从一个类中访问其他形式的对象,所以我首先在我的program.cs类中创建一个类型为“MainForm”的静态变量,它是一个Windows窗体 在DataManger.cs类中,我实例化对象“Program.MainFormObj=newmainform()”,然后调用Show方法以显示我的表单。看起来表单的绘制事件还没有完成,但它确实在绘制一些控件时启动。大概是因为主线程(这都在一个主线程上运行)被下一条语句“占用”。我想,不管已知的问题如何,我都会使用Ap
我真的卡住了。尽管在这里和使用谷歌进行了广泛的搜索,我还是找不到合适的答案。我是这样做的:但是给定的解决方案不适合我的解决方案。非常感谢您的帮助。如果这是一个大型项目,请立即投入时间对其进行重构
- 考虑一个MVC模式。您可以,而不仅仅是更新的UI技术
- 如果您不选择WinForms,则至少需要单独的UI和数据(是您的朋友)
- 当不同的表单共享公共功能时,构建可重用组件
HandleIncomingData
来调用主UI线程上的Show()
调用
应该有一种方法可以从静态方法干净地实现这一点,如下所述:
然而,当我尝试这样做时,我发现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代码:
您至少违反了Winforms编程的两条“永远不要这样做!”规则。你可能正在做的其他事情只能被猜测。以目前的形式,这不是一个可以回答的问题,请访问您当地的书店或图书馆,查找有关正确的Winforms编程技术的书籍。谢谢您的回复。不幸的是,对于这个项目,由于时间限制,我除了使用WinForms之外别无选择。今年夏天,我肯定会研究MVC模式和WPF,我同意从长远来看,这更有益。您知道我可以在解决方案的当前结构中实现的解决此问题的方法吗?没有足够的信息来确定问题是什么。你能创建一个小的测试用例来演示这个问题并发布代码,或者至少是相关的部分吗?Thx一堆,效果很好。我实际上尝试过这样一种解决方案,但我没有在LoginForm上调用Invoke方法,而是在MainForm上调用了它,它引发了一个异常,因为它尚未创建。我的理解是,当调用Invoke方法时,它会在该线程上执行lambda expressions块中的操作,因此不存在非法的跨线程操作。如果可以从LoginForm调用Invoke方法,我认为这是错误的。如果你能再帮我理解,我会很感激的。我有什么办法可以在这里给你某种形式的声誉吗?你必须完全创建并显示该形式,然后才能调用它,对吗。调用Invoke(或BeginInvoke)将调用封送到UI线程。如果你想赢得一些声誉,正确的方法是接受这个答案:-)(打勾使其变为绿色)