我正在开发一个 WPF 应用程序,其中用户可以通过按下 UI 上的按钮来启动一个进程。然后可能会提示用户完成该过程必须执行的一系列动作。视图负责将初始请求传递给域以启动流程。该视图还负责显示用户完成该过程必须执行的步骤。另一方面,域是对制定用户必须执行的步骤的直接响应。该域还能够检测用户何时完成了请求的步骤。
如果用户启动一个流程,并且该流程要求他们执行一些物理操作,那么我希望弹出一个框,其中包含描述他们必须做什么的消息。动作完成后,域会检测到它,并且窗口应该会自动关闭。
将请求从视图传递到域很简单。我使用 wpf ICommand 模式执行此操作。它以另一种我认为具有挑战性的方式传递信息。我知道绑定和 INotifyProperyChanged 接口,但我认为这不适合我正在尝试做的事情。
所以,这是我最初的尝试......
该接口由 View 实现并由 Domain 使用。它允许域与用户进行通信;
public interface IUserRequestMedium
{
/// <summary>
/// Ask the user to perform an action. User does
/// not need to provide any feedback via the user
/// interface, since it is possible for the
/// application to detect when the action has been
/// carried out by the user. The dialog will be closed
/// when either the requested action has been detected,
/// or the user aborts.
/// </summary>
/// <param name="message">
/// Request to be displayed to the user.
/// </param>
/// <param name="userAbortCallback">
/// Callback invoked by the view when the user cancels
/// the request.
/// </param>
/// <param name="actionDetectedCallback">
/// Callback invoked by the domain to confirm the
/// that the requested action has been completed.
/// </param>
void AskUserToPerformDetectableAction(
string message, Action userAbortCallback,
out Action actionDetectedCallback);
}
这是 View 代码隐藏。其中一些代码取自网络上的教程(随后被修改)。它不起作用,但我希望它能传达我的意图。
public partial class MainWindow : Window, IUserRequestMedium
{
// Constructor and other stuff...
public void AskUserToPerformDetectableAction(
string message, Action userAbortCallback,
out Action actionDetectedCallback)
{
Action closeWindow;
NewWindowThread(
() => new ActionRequestBox(message, userAbortCallback),
out closeWindow);
actionDetectedCallback = closeWindow;
}
private Window newWindow;
private void NewWindowThread(
Func<Window> construction,
out Action closeWindow)
{
var thread = new Thread(() =>
{
newWindow = construction();
newWindow.Show();
newWindow.Closed += (sender, e) => newWindow.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Window rememberedWindow = newWindow;
closeWindow = () =>
{
if (rememberedWindow != null)
rememberedWindow.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(Close));
};
}
}
这是域中的一个使用示例;
public class SomeDomainClass
{
IUserRequestMedium userRequestMedium; // assume this has been assigned in constructor
private Action notifyUserOfActionDetected;
public void PerformSomeProcess()
{
bool processCannotBeCompletedWithoutPowerCycle = ...; // some logic
if (processCannotBeCompletedWithoutPowerCycle)
{
userRequestMedium.AskUserToPerformDetectableAction(
"Please cycle the power on the external device",
CancelProcess,
out notifyUserOfActionDetected);
}
}
public void CancelProcess()
{
// User doesn't want to perform the required action
// so process must be aborted...
}
private void OnPowerCycleDetected()
{
notifyUserOfActionDetected();
}
}
我怎样才能使这项工作?这是我被抓住的跨线程方面。当域检测到该操作时,我未能成功地使窗口自动关闭。
或者,退后一步,有没有更好的方法来解决这个问题?