caliburn.microwindows-phone-8.1windows-rt

Caliburn.Micro Screen.CanClose() and MessageDialog().ShowAsync()


I'm currently using Caliburn.Micro 2.0 for my Windows Phone 8.1 project (Universal App) and I'm having problem with conditionally cancelling page close after user clicks a MessageDialog button.

It seems that Caliburn closes page after leaving CanClose() method, not waiting for the callback which is called after async MessageDialog.

public class MyViewModel: Screen
{
  public override async void CanClose(Action<bool> callback)
  {     
    MessageDialog dlg = new MessageDialog("Close?","Confirmation");
    dlg.Commands.Add(new UICommand() { Id = 0,  Label = "Yes" });
    dlg.Commands.Add(new UICommand() { Id = 1,  Label = "No"  });       

    var result = await dlg.ShowAsync();

    callback((int)result.Id == 0);  
  }
}

Solution

  • The only solution I have at the moment is set a field with a flag indicating if the page can be closed. On the user attempt to navigate back I tell Caliburn to abort the close and I display the confirmation dialog. When I get the result I set the flag to true and navigate back manually. This causes another call to CanClose, but this time I set the callback to true and skip the dialog part.

    I don't like this solution much, but it is only way I managed to solve this problem.

    private bool canClose = false;
    
    public override async void CanClose(Action<bool> callback)
    {
      callback(canClose);
    
      if (!canClose)
      {
        MessageDialog dlg = new MessageDialog("Close?","Confirmation");
        dlg.Commands.Add(new UICommand() { Id = 0,  Label = "Yes" });
        dlg.Commands.Add(new UICommand() { Id = 1,  Label = "No"  });       
    
        var result = await dlg.ShowAsync();
    
        if ((int)result.Id == 0)
        {
          canClose = true;
          navigationService.GoBack();
        }
      }
    }
    

    PS: I don't use MessageDialog directly in my ViewModel, I'm using a dialog service interface for popups. I just used it here to demonstrate the issue.