Winforms 如何制作';部分';模态对话?

Winforms 如何制作';部分';模态对话?,winforms,Winforms,是否有一种方法可以开始以模态方式显示对话框,但不是隐藏它,而是在将其更改为非模态对话框时保持其可见 我想显示一个对话框,阻止显示对话框的方法。然后,当用户单击我想要的对话框上的“完成”按钮时: 对话框将保持可见 控件返回到显示对话框的方法 我通过在单独的STA线程上运行对话框,并使用事件阻止主UI线程,直到按下“Finish”(完成),实现了这个结果,但是这个方法有一个缺点:当对话框可见时,您可以单击“main”(主)窗口的close(关闭)按钮,当对话框隐藏时,主窗口关闭 更新 感谢到目前

是否有一种方法可以开始以模态方式显示对话框,但不是隐藏它,而是在将其更改为非模态对话框时保持其可见

我想显示一个对话框,阻止显示对话框的方法。然后,当用户单击我想要的对话框上的“完成”按钮时:

  • 对话框将保持可见
  • 控件返回到显示对话框的方法
我通过在单独的STA线程上运行对话框,并使用事件阻止主UI线程,直到按下“Finish”(完成),实现了这个结果,但是这个方法有一个缺点:当对话框可见时,您可以单击“main”(主)窗口的close(关闭)按钮,当对话框隐藏时,主窗口关闭

更新 感谢到目前为止的回复。抱歉-看起来我在太多的背景和不够的背景之间取得了错误的平衡

该表单实际上是一个模式“向导”对话框——它出现在主应用程序前面,然后隐藏。因此,就用户而言,没有出现非标准的奇怪现象。唯一的区别是对话框是由UI线程的一系列回调驱动的,因此我认为在其生命周期内使其真正成为模态(通过调用ShowDialog)是行不通的。第一个回调必须显示对话框,然后在用户通过对话框UI设置其首选项时阻塞。之后,对话框保持可见并显示进度条页面,同时从UI线程进行各种其他回调。最终,形式被隐藏了。表单打开时,用户未与主窗口交互。就他们而言,主UI线程应该是100%模态wrt

(该表单是VisualStudio向导的一个对话框-它们由UI线程上的一系列回调驱动)。另一种方法是显示对话框,隐藏它,立即显示最上面的“进度”表单,然后隐藏它,但我认为显示单个对话框对用户来说是一种更无缝的体验


再一次-抱歉造成混乱

也许你想重新思考你的互动模式?你将如何向用户解释这一点?他们有一个内部化的计算机程序工作模式,你最好有一个很好的理由打破这个模式。他们知道模态对话,他们知道非模态对话,他们知道检查员。选择一个,然后应用它

模态对话框用于短时交互。它们不应阻止退出应用程序。用户控制交互,程序只提供所需的最小限制

[解释后,替换] 在模式对话框中显示进度条有什么问题?确定后立即开始处理
是否单击,禁用所有按钮,仅保持“取消”按钮处于活动状态?如果需要很长时间,用户可能希望中止该操作。只有在完成处理后才能关闭对话框。

您可以使用无模式对话框,然后让主UI检查用户是否单击了“完成”按钮。如果无模式对话框处于打开状态,但尚未单击“完成”,则不要响应主窗体中的任何用户操作…

这只是一个糟糕的想法-这是完全非标准的行为,您将跳过各种各样的障碍,以使某些功能正常工作,这会让您的用户感到非常困惑。

我会让它成为一个错误从应用程序的侧面或底部弹出,将其他东西推到一边。如果它位于用户可能需要查看或与之交互的其他内容之上,那么它只会惹恼他们

与这里提到的大多数其他答案一样,您正在实现非标准的UI元素,这会让大多数用户感到困惑

如果对话框保持可见只是为了提供对数据的只读访问,那么为什么不让对话框窗口正常关闭,并使用对话框窗口中的数据在应用程序中打开一个侧栏窗口

如果对话框保持可见,允许用户继续在其中进行更新,那么也许,它一开始就不应该是模态的


关键是,有两种不同的方法可以在不破坏标准UI隐喻的情况下完成任务。

我发现在交互的阻塞阶段在主UI线程上显示一个不可见的模式对话框非常有效

隐藏模式对话框设置(因此不可见):ShowInTaskBar=false,FormBorderStyle=None,size={0,0},不透明度=0%,StartupPosition=CenterParent

隐藏对话框使用ShowDialog显示在UI线程上。可见对话框显示在单独的STA线程上。在主UI线程上调用hiddenDialog.ShowDialog之前,将启动该线程

当visible对话框希望初始阻塞状态完成时,它会隐藏hiddenDialog。这将阻止主UI线程阻塞

重要的代码位:

void LaunchWizardForm(s)
{
  // Show the wizard on its own thread.
  ThreadStart t = () =>
  {
    _wizard = new WizardForm(s);
    Application.Run(new ApplicationContext(_wizard));
  };
  var thread = new Thread(t);
  thread.SetApartmentState(ApartmentState.STA);
  thread.Start();

  // Block this (main UI) thread
  _hiddenForm.ShowDialog();
}

void EndModalEpisode()
{
    _hiddenForm.Invoke((Action) (() => _hiddenForm.Hide()));
}

希望进一步的解释有助于澄清用户交互。这绝对是一个模式对话框-它是在创建新项目时从用户处获取设置,然后在生成项目时显示进度条。您需要注意不透明度,它可能会故障切换远程桌面和一些(尽管是垃圾)视频卡