c# - 如何将用户交互封装在一个方法中

标签 c# winforms message-pump

我正在使用一个外部框架,该框架定义了一个具有单一方法的接口(interface):

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

消息泵有一些缺陷:

  • 丑陋且 cpu 效率不高

  • 使用 White UIAutomation 时速度非常慢

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

最佳答案

我想你快到了。

显示一个包含用户输入控件的模态对话框,并让该对话框在需要时调用 Authenticate 方法。

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

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

*在此处编辑 *

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

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

关于c# - 如何将用户交互封装在一个方法中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8725465/

相关文章:

c# - Windows Phone 8.1 - 在 gridview 上使用图片库图像进行数据虚拟化

c# - Application.Run 在 Application.Exit 之后在同一个线程上不工作

C# 如何以编程方式重新定位 DataGridView 上的行选择

c# - 控制台应用程序中的消息泵

windows - 测量 Windows 应用程序的 UI 响应能力

c# - 如何将 xml 绑定(bind)到 wpf TreeView ?

c# - 在 CoreFx 上使用 System.Data.SqlClient 时出现 UDT 不支持的 token 问题

c# - 我可以进一步减少对由docker容器上的asp.net Web API应用程序运行的docker镜像的依赖性

c# - 如何更改 Windows 窗体 LinkLabel 的文本和链接

winforms - 如何配置适用于 Azure 的 CSLA WCF 数据门户?