Search code examples
c#.netavaloniauiavalonia

Avalonia UI MessageBox freezing


I'm new to Avalonia UI, I'm building simple app and am using MessageBox.Avalonia. I want to write a service for showing dialogs. I came up with this:

public class UserDialogService {
    public async Task<ButtonResult> ShowDialog(string title, string message, ButtonEnum button = ButtonEnum.Ok) {
        var dialog = MessageBoxManager.GetMessageBoxStandard(title, message, button);
        var result = await dialog.ShowAsync();
        return result;
    }
}

My problem is that this MessageBox freezes and it's buttons cannot be clicked.

I'm using it like that:

try {
    CreateAppDirectoryIfNotExists();
    Settings = DbSettings.ReadDbSettings();
} catch (Exception exc) {
    if (exc is ConfigurationException) {
        var result = DialogService.ShowDialog("Configuration Error", "The configuration file was not found or was invalid. Should default configuration be written?", ButtonEnum.YesNo).GetAwaiter().GetResult();
        if (result == ButtonResult.Yes) {
            Settings = new DbSettings();
            Settings.WriteDbSettings();
        }
    }
    throw new Exception("Failed to setup application.", exc);
}

I've tried to modify the service to launch dialog.ShowAsync() in new thread using Task.Run() but nothing was shown. What am I doing wrong?

Edit #1:

I've tried using Dispatcher.UIThread.InvokeAsync() like this:

public ButtonResult ShowDialog(string title, string message, ButtonEnum button = ButtonEnum.Ok) {
    var dialog = MessageBoxManager.GetMessageBoxStandard(title, message, button);
    return Dispatcher.UIThread.InvokeAsync(dialog.ShowWindowAsync).GetAwaiter().GetResult();
}

It didn't help. Nothing is showing up with that approach.


Solution

  • Fixed by adding callback:

    public void ShowDialog(string title, string message, ButtonEnum button = ButtonEnum.Ok, Action<ButtonResult>? callback = null) {
        var dialog = MessageBoxManager.GetMessageBoxStandard(title, message, button);
        Dispatcher.UIThread.InvokeAsync(async () => {
            var result = await dialog.ShowAsync();
            callback?.Invoke(result);
        });
    }
    

    Usage:

    DialogService.ShowDialog("Title", "Text", ButtonEnum.YesNo, DialogCallback);
    
    private void DialogCallback(ButtonResult result) {
        //React on button clicked
    }