我继承了一个Winforms应用程序,该应用程序从UI线程对应用程序服务器执行大量长时间运行的调用,因此UI在相当长的一段时间内保持无响应,无法使用,无法关闭。 (这让我真的去了 AAAAAAAAAARGH!)
我计划将服务器调用移到后台线程并禁用UI - 但可移动&可关闭 - 当后台线程完成它的工作。
那么阻止用户输入我的应用程序的最佳方法是什么?我正在思考“模态进度对话框”,但我更喜欢一种不会强迫我将视觉效果抛到用户面前的解决方案(某些服务器操作在不到500毫秒内运行,因此对话框是不最佳...)
Winforms中是否有任何方法可以阻止用户启动操作或更改应用程序中的数据,同时通过一些选择(调整大小,显示,隐藏和家人以及关闭窗口的用户)?我更喜欢一种不会让我访问表单中的每个UI元素并将其设置为禁用的方式...它们中有很多并且该应用程序确实“在UI设计器中被黑客攻击,直到它显示出华而不实的东西“源代码的风格。在发布日期之前,没有办法重构每个有臭味的东西......
哦,顺便说一下,这个应用程序存在于.net framework 2
中答案 0 :(得分:6)
我知道的唯一方法是将部分/全部控件设置为禁用。但是,根据控件的布局方式,不必将每个控件设置为禁用 - 当禁用容器控件时,也会禁用其所有子控件。例如,如果您有GroupBox
包含某些控件,如果您将GroupBox
设置为禁用,那么GroupBox
中的所有控件也将被禁用。
答案 1 :(得分:5)
选择一些上层容器控件(可能是表单本身),并将其Enabled属性设置为false。放置在该控件上的所有控件都将被禁用,这将阻止它们接收输入。
答案 2 :(得分:3)
简单地启用/禁用按钮的问题是,在任务运行时,UI事件仍会被添加到消息队列中....
假设您有“搜索”按钮和“重置”按钮。单击“搜索”时,将禁用这两个按钮。搜索运行了一段时间。如果用户单击“重置”,即使它已被禁用,搜索也会在完成后立即重置。
快速而肮脏的方法是添加
Application.DoEvents();
在重新启用按钮之前立即调用。 DoEvents()将处理控件上的所有单击事件,对于仍然禁用的控件,将忽略这些事件。
答案 3 :(得分:1)
在Win32 API级别上,有一个EnableWindow函数,您可以禁用任何窗口处理(当然,您需要获取主窗口的底层句柄,以及任何其他顶级窗口)。不过,我还没有在WinForms中测试它。 (我很确定User32级别还有其他答案,但我现在还记不起API调用了。)
注意:这不会使控件变灰,从可用性的角度来看会降低其效用(用户只看到“冻结的应用程序”)。如果你至少设置一个沙漏光标,它会稍微好一点。
但是,这是一种处理异步处理的快捷方式。您真的需要将用户锁定在整个应用程序之外吗?也许只是在请求正在进行时应该禁止的一些功能?
答案 4 :(得分:0)
不幸的是,使用WinForms,您可能需要在单个共享方法中禁用/启用按钮。这是WPF为Windows窗体带来的优势之一 - 处理这些情况要容易得多。
至于不阻止你的UI - 你需要将你的调用转移到异步编程模型。在您的情况下,我建议您查看ThreadPool。
你想要做的事情就是让按钮禁用你的控件,在线程池上调用你的操作,然后在完成时重新启用它们。
答案 5 :(得分:0)
我在这里回答了一个旧帖子,但是我看到了这个问题并想起了我的一个旧的WinForm应用程序,我遇到了同样的问题,即禁用表单同时仍然允许它重新调整大小并移动等等。我加载了我的代码,发现解决方案是:
严格来说,您不必使用Panel控件,任何Container Control应该表现出相同的行为。即使是PictureBox控件也可以做到这一点!