Reputation: 1502
I tried to implement a DialogManager like described here. I'm not using caliburn, so I refactored a bit, and also it's no longer SimpleDialog but CustomDialog, but there weren't big changes.
So now when I click a button that calls DialogManager.ShowDialog
and wait for the resulting task with task.Wait()
the application just freezes (as aspected for wait) but without showing the dialog. I tried to debug, but it works alright until the line
await Application.Current.Windows.OfType<MetroWindow>().First().ShowMetroDialogAsync(dialog);
. dialog is a valid BaseMetroDialog
and i get the right window from the Application.Cur...
call. It also happens when I'm just calling ShowMessageAsync
, so the problem seems to be in the connection of the call and the waiting for the task. Is there no way to really block the following execution (forcing the dialog to be modal)?
If you need additional information please comment, I'll extend the question, but right now I don't know what to show besides the code already linked at the beginning.
Upvotes: 1
Views: 927
Reputation: 62045
This is all the gimmicks I had to do in order to get this to work without having to use async/await:
using SysThread = System.Threading;
using WpfThread = System.Windows.Threading;
using SysTasks = System.Threading.Tasks;
using MahCtl = MahApps.Metro.Controls;
using MahDlg = MahApps.Metro.Controls.Dialogs;
using Wpf = System.Windows;
.
.
.
private SysThread.CancellationTokenSource tokenSource;
.
.
.
MahCtl.MetroWindow parentMetroWindow = Wpf.Application.Current.Windows.OfType<MahCtl.MetroWindow>().First();
var metroDialogSettings = new MahDlg.MetroDialogSettings();
metroDialogSettings.OwnerCanCloseWithDialog = true; //does not appear to have any effect
metroDialogSettings.AnimateHide = false;
metroDialogSettings.AnimateShow = false;
using( tokenSource = new SysThread.CancellationTokenSource() )
{
metroDialogSettings.CancellationToken = tokenSource.Token;
SysTasks.Task<MahDlg.MessageDialogResult> task = MahDlg.DialogManager.ShowMessageAsync( parentMetroWindow, title, message, mahStyle, metroDialogSettings );
parentMetroWindow.Closing += onMainWindowClosing;
while( !(task.IsCompleted || task.IsCanceled || task.IsFaulted) )
Wpf.Application.Current.Dispatcher.Invoke( WpfThread.DispatcherPriority.Background, new Action( delegate { } ) );
parentMetroWindow.Closing -= onMainWindowClosing;
return task.Result;
}
.
.
.
private void onMainWindowClosing( object sender, SysCompMod.CancelEventArgs cancelEventArgs )
{
tokenSource.Cancel();
}
The extra handler for the Closing
event of the main window is necessary in order to handle the situation where the user attempts to close the main window of your application via the task bar, and while a modal dialog box is open, because OwnerCanCloseWithDialog
does not seem to have any effect, or it was never meant to do what the documentation tricked me into believing that it was perhaps meant to do.
Upvotes: 0
Reputation: 8706
You mention task.Wait(). If you started a task to show the dialog, I'm afraid you can't do that. The GUI is single threaded. You can still await the result, just has to be initiated from the main thread, not a task.
Upvotes: 1