简体   繁体   English

用户单击MVVM的关闭按钮时,如何在WPF对话框中取消等待?

[英]How can I cancel an Await in a WPF dialog when the user clicks the close button with MVVM?

I have an application that requires a user to enter SQL connection information in a dialog. 我有一个需要用户在对话框中输入SQL连接信息的应用程序。 When the user clicks the "Connect" button, I await the result of SqlConnection.OpenAsync() with the supplied credentials in order to test that they are valid before closing the dialog box. 当用户单击“连接”按钮时,我将await带有提供的凭据的SqlConnection.OpenAsync()的结果,以便在关闭对话框之前测试它们是否有效。 I also disable the Connect button to avoid duplicate attempts. 我也禁用了“连接”按钮,以避免重复尝试。 When the credentials are correct, it returns almost immediately, but when they are not, it can take up to 30 seconds to return. 如果凭据正确无误,则几乎立即返回,而如果凭据不正确,则最多可能需要30秒才能返回。 The cancel button is able to use a CancellationToken to cancel the request and close the dialog. 取消按钮可以使用CancellationToken取消请求并关闭对话框。

The problem is that the user is still able to click the window's close button on the dialog to dismiss it. 问题是用户仍然可以单击对话框上窗口的关闭按钮将其关闭。 My view model doesn't get notified, but the form is still closed. 我的视图模型没有得到通知,但表单仍处于关闭状态。 30 seconds or so later the connection attempt returns with error information, and shows a message box. 30秒钟左右后,连接尝试将返回错误信息,并显示一个消息框。

Is there a good, MVVM friendly way, to cancel the connection attempt with my CancelationToken when the form is closed in this way? 当以这种方式关闭表单时,是否有一种很好的,MVVM友好的方法来取消我的CancelationToken的连接尝试? I know that I could rig up something using in the dialog's code-behind, but I'd like to avoid referencing the view model from there. 我知道我可以在对话框的后台代码中使用某些东西,但是我想避免从那里引用视图模型。

Depending on what you are using for your MVVM infrastructure, you could use something like MVVM Light's EventToCommand on the Window.Closing . 根据用于MVVM基础结构的内容,可以在Window.Closing上使用MVVM Light的EventToCommand之类的东西。 You may bind this event to the cancellation command that you have attached to the button. 您可以将此事件绑定到已附加到该按钮的取消命令。

See MVVM Light: Adding EventToCommand in XAML without Blend, easier way or snippet? 请参阅MVVM Light:在XAML中添加EventToCommand而不使用Blend,更简便的方法或摘要? for a way to do this. 一种实现此目的的方法。

尝试等待SqlConnection.OpenAsync()的结果并传递取消令牌。

You can write an extension-method therefor. 您可以为此编写扩展方法。

So you have a class (let's call it WindowExtensions) where your attached property is definded. 因此,您拥有一个类(我们将其称为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);
    }
}

In your XAML on the Window-Element you can map your attached-property to an ICommand-Property in your ViewModel like: 在Window-Element上的XAML中,您可以将附加属性映射到ViewModel中的ICommand-Property,例如:

nameSpaceOfWindowExtensions:WindowExtensions.WindowClosingCommand="{Binding WindowClosingCommand}"

And in your ViewModel you have a ICommand -Property where you can handle it. 在ViewModel中,您可以使用ICommand -Property。 Something like: 就像是:

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;
    }
}

If you don't need the CancelEventArgs in your ViewModel, just modify the following line in the attached-property: 如果您的ViewModel中不需要CancelEventArgs,只需在附加属性中修改以下行:

windowClosingCommand.Execute(e);

to

windowClosingCommand.Execute(null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当用户在其外部单击时,关闭WPF对话框窗口 - close a WPF Dialog Window when the user clicks outside it WPF UserControl MVVM如何关闭对话框 - WPF UserControl MVVM how to close a dialog 用户单击WPF应用程序中的主窗口时如何关闭窗口 - How to close a window when user clicks on mainwindow in wpf application 当我按下 WPF Mvvm 中的按钮时,如何在 DataGrid 中显示数据? - How can I show data in DataGrid when I press button in WPF Mvvm? 实现MVVM时,如何更新WPF的数据网格中的行? (没有任何按钮) - How Can I update a row in WPF's datagrid when I 'm implementing MVVM ? ( without any Button) 用户双击该文件时,如何在WPF应用程序中打开该文件? - How can I open a file in my WPF app, when the user double-clicks on that file? 当用户单击“取消”按钮并退出时,放弃在Gridcontrol中所做的更改 - Discard changes made in a Gridcontrol when a user clicks the “Cancel” button and exit 如何通过ok函数关闭OpenFileDialog并在MVVM模式silverlight中取消? - How can I close OpenFileDialog by functions ok and cancel in MVVM pattern silverlight? 如何强制DropDownList样式ComboBox仅在用户单击下拉按钮时打开? - How can I force a DropDownList style ComboBox to only open when the user clicks the drop-down button? WPF MVVM等待:取消任务不会停止我的进度栏 - WPF MVVM await: Cancel task does not stop my progressbar
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM