为什么这个C#代码执行顺序不正确?不异步(至少我不这么认为)

为什么这个C#代码执行顺序不正确?不异步(至少我不这么认为),c#,uwp,mvvm-light,C#,Uwp,Mvvm Light,有人能帮我理解为什么我对dialogservice的调用在CannaviGateway函数返回其值后执行吗?(我的目标是警告用户,他们将在不保存更改的情况下离开视图。如果他们单击“确定”,则允许导航。我使用的是MVVM Light 当我一步一步地浏览代码时,它确实到达了dialog服务,但在创建对话框之前,它会进入Cannavigateway的末尾。OnNavigatingFrom调用Cannavigateway方法 public bool CanNavigateAway() {

有人能帮我理解为什么我对dialogservice的调用在CannaviGateway函数返回其值后执行吗?(我的目标是警告用户,他们将在不保存更改的情况下离开视图。如果他们单击“确定”,则允许导航。我使用的是MVVM Light

当我一步一步地浏览代码时,它确实到达了dialog服务,但在创建对话框之前,它会进入Cannavigateway的末尾。OnNavigatingFrom调用Cannavigateway方法

public bool CanNavigateAway()
    {
        if (!changesSaved && Model.IsModified && !continueNavigation)
        {             
              dialogService.ShowMessage("Are you sure you want to continue?",
              "Confirmation",
              buttonConfirmText: "Continue", buttonCancelText: "Discard",
              afterHideCallback: (confirmed) =>
              {
                  if (confirmed)
                  {
                      // User has pressed the "confirm" button.
                      // ...
                      continueNavigation = true;
                  }
                  else
                  {
                      // User has pressed the "cancel" button
                      // (or has discared the dialog box).
                      // ...
                      continueNavigation = false;
                  }
              });
            return continueNavigation;
        }
}
以下是MVVM Light可绑定页面类中的OnNavigationFrom方法:

protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        var navigableViewModel = this.DataContext as INavigable;

        if (navigableViewModel != null)
        {
            if (!navigableViewModel.CanNavigateAway())
            {
                e.Cancel = true;
            }
        }
    }
我尝试了一种不同的方法来从混合中获取对话服务,但showConfirmationDialogAsync似乎仍然没有及时执行:

public bool CanNavigateAway()
{
    continueNavigation = false;
    if (!changesSaved && Model.IsModified && !continueNavigation)
    {
        showConfirmationDialogAsync();
        return continueNavigation;
    }  

private async void showConfirmationDialogAsync()
{
    continueNavigation = false;
    ContentDialog noSaveConfirmation = new ContentDialog
    {
        Title = "Warning",
        Content = "You have unsaved changes. Are you sure you want to leave this page without saving?",
        PrimaryButtonText = "Leave without saving",
        SecondaryButtonText = "Stay and finish"
    };

    ContentDialogResult result = await noSaveConfirmation.ShowAsync();

    if (result == ContentDialogResult.Primary)
    {
        continueNavigation = true;
    }
    else if (result == ContentDialogResult.Secondary)
    {
        continueNavigation = false;
    }
}        

如果您需要用户的响应,则所有解决方案都不起作用。问题是,当代码位于导航事件处理程序中时,它将在UI线程上运行,并且用户提示将异步运行,因此UI可以自由地向用户显示对话框。然而,这意味着事件处理程序在用户启动之前完成这是一个回应的机会

但是,您可以使用变通解决方案。添加一个标志
bool
字段,如
forceNavigation
。然后在
OnNavigatingFrom
中向用户显示对话框,并立即将
Cancel
设置为
true
并向用户显示确认对话框。如果用户说是,则设置
forceNavigait
设置为true并再次手动触发导航。现在它将跳过确认部分并立即导航

protected async override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{ 
    //if navigation is forced, skip all logic
    if ( !forceNavigation )
    {
        var navigableViewModel = this.DataContext as INavigable;

        if (navigableViewModel != null)
        {
            e.Cancel = true;
            //display the dialog to the user, if he says yes, set
            //forceNavigation = true; and repeat the navigation (e.g. GoBack, ... )
        }
    }
}

您只将委托传递给
ShowMessage
函数,它们不会立即被调用。由于您没有提供dialogService类型,因此无法确定,但它可能在消息泵上排队,因此实际上是异步的。处理它的一种方法是更改回调以触发事件“OnNavigatingFromConfirmed”并将返回类型设为void而不是bool。但还有其他方法回调是一种处理异步编程的模式。隐藏对话框后将调用lambda
afterHideCallback
,但方法
CannaviGateway()
将以非阻塞方式立即返回。不幸的是,我无法对[uwp]或[mvvm light]发表评论。谢谢大家。我已经进行了重构,尝试简单。此版本不使用mvvm light对话服务。不过,我仍然有同样的问题。我在这一点上真的很困惑。“ShowAsync”“是一个即将发生的重入性错误。但是很容易诊断,您可以在调试器的堆栈跟踪中看到它。很高兴它有帮助!很高兴编码:-)