如何在单个方法中封装用户交互

时间:2012-01-04 10:40:41

标签: c# winforms message-pump

我正在使用外部框架来定义具有单个方法的接口:

bool Authenticate();

即包含整个身份验证过程,包括用户交互(WinForms)。我想做的是:

bool Authenticate()
{
  bool succeeded = false;
  bool userCancelled = false;
  while(!succeeded && !userCancelled)
  {
     var credentials = AskTheUserForCredentials(); // this needs to wait for user input before returning!
     if (credentials == null) 
       userCancelled = true;
     else
       succeeded = AuthenticateWithAnExternalServer(credentials);

     if (!succeeded)
       ShowErrorMessage();
  }
  return succeeded;
}

现在,实现AskTheUserForCredentials()ShowErrorMessage()的简便方法是在内部使用Form.ShowDialog()。这是非常糟糕的用户体验,因为对话框在实际身份验证过程中消失,并且错误消息出现在新的,不必点击关闭的对话框中。

我宁愿把它全部放在一个单独的表单中,保持可见,适当地禁用文本框/按钮并单独显示错误信息。

你如何在这个单一的阻塞方法调用中做到这一点?

更新

到目前为止,最佳解决方案是在AskTheUserForCredentials()

中实施消息泵
Credentials AskTheUserForCredentials()
{
   while(NeitherOkNorCancelPressed())
   {
      Application.DoEvents();
      Thread.Sleep(10); // Standard Sleep(0) results in 100% procesor core usage.
   }
   return CreateCredentialsFromTextboxesEtc();
}

现在我们都知道消息泵远非干净。

这个解决方案究竟有多糟糕?

还有什么更好的吗?

更新2

消息泵有一些陷阱:

  • 丑陋且不完全有效c

  • 使用White UIAutomation

  • 工作得非常慢

我最终将整个过程委托给ChrisBD对话框(对话框仅在最终成功或失败后关闭)。这花费了更多的时间来使用IoC将身份验证从GUI抽象出来,但最终是干净的并按预期工作。

1 个答案:

答案 0 :(得分:1)

我认为你快到了。

显示具有用户输入控件的模式对话框,并在需要时让该对话框调用Authenticate方法。

然后,您可以选择对话框何时关闭以及确实显示任何错误消息的位置。

让模态对话框类的属性指示身份验证是否成功。当您关闭对话框类(由主应用程序在模态打开它之前实例化)后,主应用程序将继续运行 - 然后您可以通过检查相应的对话框类属性来检查身份验证是否成功。 / p>

* 在这里编辑*

如果您自己实现Authenticate方法,则此函数调用模态对话框,而不是您的主应用程序(如前所述)。自定义表单类可以运行所有身份验证逻辑,并显示用户交互控件以及任何错误消息。请记住删除最小化和关闭按钮,并设置类属性以指示身份验证过程成功或失败。

调用框架将等待您的身份验证方法的返回值。