我有一个应用程序,它要求用户在对话框中输入SQL连接信息。当用户单击"连接"按钮时,我将await
SqlConnection.OpenAsync()
的结果与提供的凭据进行比较,以便在关闭对话框之前测试它们是否有效。我还禁用了"连接"按钮以避免重复尝试。当凭据正确时,它几乎会立即返回,但如果凭据不正确,则可能需要长达30秒的时间才能返回。取消按钮可以使用CancellationToken
取消请求并关闭对话框。
问题是,用户仍然可以单击对话框上的窗口关闭按钮来关闭它。我的视图模型没有收到通知,但表单仍然关闭。大约30秒后,连接尝试返回错误信息,并显示一个消息框。
当表单以这种方式关闭时,是否有一种好的、MVVM友好的方法来取消与我的CancelationToken
的连接尝试?我知道我可以在对话框的代码后面使用来装配一些东西,但我希望避免从那里引用视图模型。
根据MVVM基础设施的使用情况,您可以在Window.Closing
上使用类似MVVM Light的EventToCommand
的东西。您可以将此事件绑定到已附加到按钮的取消命令。
请参阅MVVM Light:在没有Blend的XAML中添加EventToCommand,更简单的方法或片段?想办法做到这一点。
尝试等待SqlConnection的结果。OpenAsync()并传入取消令牌。
您可以为此编写一个扩展方法。
因此,您有一个类(让我们称之为WindowExtensions),其中定义了附加属性。
internal class WindowExtensions
{
public static readonly DependencyProperty WindowClosingCommandProperty = DependencyProperty.RegisterAttached(
"WindowClosingCommand", typeof (ICommand), typeof (WindowExtensions), new PropertyMetadata(null, OnWindowClosingCommandChanged));
private static void OnWindowClosingCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Window window = d as Window;
if (window == null)
return;
if (e.NewValue != null)
{
window.Closing += WindowOnClosing;
}
}
private static void WindowOnClosing(object sender, CancelEventArgs e)
{
Window window = sender as Window;
if (window == null)
return;
ICommand windowClosingCommand = GetWindowClosingCommand(window);
windowClosingCommand.Execute(e);
}
public static void SetWindowClosingCommand(DependencyObject element, ICommand value)
{
element.SetValue(WindowClosingCommandProperty, value);
}
public static ICommand GetWindowClosingCommand(DependencyObject element)
{
return (ICommand) element.GetValue(WindowClosingCommandProperty);
}
}
在Window元素上的XAML中,您可以将附加的属性映射到ViewModel中的ICommand属性,如:
nameSpaceOfWindowExtensions:WindowExtensions.WindowClosingCommand="{Binding WindowClosingCommand}"
在您的ViewModel中,您有一个ICommand
-属性,您可以在其中处理它。类似于:
private ICommand windowClosingCommand;
public ICommand WindowClosingCommand
{
get { return windowClosingCommand ?? (windowClosingCommand = new RelayCommand(OnWindowClosing)); }
}
private void OnWindowClosing(object parameter)
{
CancelEventArgs cancelEventArgs = parameter as CancelEventArgs;
if (cancelEventArgs != null)
{
// If you want to cancel the closing of the window you can call the following:
//cancelEventArgs.Cancel = true;
}
}
如果您在ViewModel中不需要CancelEventArgs,只需修改附加属性中的以下行:
windowClosingCommand.Execute(e);
至
windowClosingCommand.Execute(null);