我正在使用外部框架来定义具有单个方法的接口:
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抽象出来,但最终是干净的并按预期工作。
答案 0 :(得分:1)
我认为你快到了。
显示具有用户输入控件的模式对话框,并在需要时让该对话框调用Authenticate方法。
然后,您可以选择对话框何时关闭以及确实显示任何错误消息的位置。
让模态对话框类的属性指示身份验证是否成功。当您关闭对话框类(由主应用程序在模态打开它之前实例化)后,主应用程序将继续运行 - 然后您可以通过检查相应的对话框类属性来检查身份验证是否成功。 / p>
* 在这里编辑*
如果您自己实现Authenticate方法,则此函数调用模态对话框,而不是您的主应用程序(如前所述)。自定义表单类可以运行所有身份验证逻辑,并显示用户交互控件以及任何错误消息。请记住删除最小化和关闭按钮,并设置类属性以指示身份验证过程成功或失败。
调用框架将等待您的身份验证方法的返回值。