“任何时候只能打开一个ContentDialog。”打开另一个contentdialog时出错

我正在使用Windows.UI.Xaml.Controls.ContentDialog来显示确认。 根据第一个对话框的响应,我会(或不会)显示另一个对话框。 但是,当我尝试打开第二个内容对话框时,它会抛出:“任何时候都只能打开一个ContentDialog。” 错误。 即使在UI中,第一个对话框将被关闭但不知何故我仍然无法打开第二个对话框。 任何的想法?

我已经创建了一些代码来处理我的应用程序中的这种类型的难题:

 public static class ContentDialogMaker { public static async void CreateContentDialog(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); } public static async Task CreateContentDialogAsync(ContentDialog Dialog, bool awaitPreviousDialog) { await CreateDialog(Dialog, awaitPreviousDialog); } static async Task CreateDialog(ContentDialog Dialog, bool awaitPreviousDialog) { if (ActiveDialog != null) { if (awaitPreviousDialog) { await DialogAwaiter.Task; DialogAwaiter = new TaskCompletionSource(); } else ActiveDialog.Hide(); } ActiveDialog = Dialog; ActiveDialog.Closed += ActiveDialog_Closed; await ActiveDialog.ShowAsync(); ActiveDialog.Closed -= ActiveDialog_Closed; } public static ContentDialog ActiveDialog; static TaskCompletionSource DialogAwaiter = new TaskCompletionSource(); private static void ActiveDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args) { DialogAwaiter.SetResult(true); } } 

要使用这些方法,您需要在变量中创建ContentDialog及其内容,然后将变量和bool传递给Method。

如果您的应用程序代码中需要回调,请使用CreateContentDialogAsync(),例如,如果对话框中有一个按钮,并且您希望等待按下按钮,然后在对话框后从代码中获取表单中的值。

如果您不需要等待UI代码中的Dialog完成,请使用CreateContentDialog()。

使用awaitPreviousDialog等待上一个对话框完成后再显示下一个Dialog,或设置为false,删除上一个Dialog,然后显示下一个Dialog,比如说,如果你想显示一个Error Box,或者下一个Dialog更重要。

例:

 await ContentDialogMaker.CreateContentDialogAsync(new ContentDialog { Title = "Warning", Content = new TextBlock { Text = "Roaming Appdata Quota has been reached, if you are seeing this please let me know via feedback and bug reporting, this means that any further changes to data will not be synced across devices.", TextWrapping = TextWrapping.Wrap }, PrimaryButtonText = "OK" }, awaitPreviousDialog: true); 

任何时候都只能打开一个ContentDialog。

这是事实。 ( 我真的很惊讶,但只是片刻 )你不能在任何时候拥有多个,这更像是微软的指南,因为在彼此之上有多个对话框填充内容真的很麻烦。

尝试更改您的UX以仅显示一个复杂的ContentDialog,并且对于所有其他消息使用MessageDialog – 它支持多个按钮( 仅限两个用于手机,但更多用于桌面 )用于用户响应,但没有Checkbox或类似的“智能”内容。

在我的情况下,MessageDialogs确实很有帮助,但在某些领域我使用链式 ContentDialogs,但为此你必须 等待第一个,并在没有任何例外的情况下立即打开第二个。 在您的情况下,当您尝试打开下一个时,似乎ContentDialog未完全关闭。

希望能帮助到你!

威廉布拉德利的上述方法很好。 只是稍微改进一下,这是一个提交和等待显示内容对话框的扩展方法; 在已经提交的所有其他内容对话框之后,将显示该对话框。 注意:当用户点击之前的积压对话框时,您可能不再希望显示已提交的对话框; 为了表明这一点,您可以传递一个谓词,该谓词将在其他对话框被解除后进行测试。

 static public class ContentDialogExtensions { static public async Task EnqueueAndShowIfAsync( this ContentDialog contentDialog, Func predicate = null) { TaskCompletionSource currentDialogCompletion = new TaskCompletionSource(); TaskCompletionSource previousDialogCompletion = null; // No locking needed since we are always on the UI thread. if (!CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess) { throw new NotSupportedException("Can only show dialog from UI thread."); } previousDialogCompletion = ContentDialogExtensions.PreviousDialogCompletion; ContentDialogExtensions.PreviousDialogCompletion = currentDialogCompletion; if (previousDialogCompletion != null) { await previousDialogCompletion.Task; } var whichButtonWasPressed = ContentDialogResult.None; if (predicate == null || predicate()) { whichButtonWasPressed = await contentDialog.ShowAsync(); } currentDialogCompletion.SetResult(null); return whichButtonWasPressed; } static private TaskCompletionSource PreviousDialogCompletion = null; } 

另一种方法可能是使用SemaphoreSlim(1,1)。

我知道这个问题已经过时了,但我的回答可能会帮助那些面临这个问题的人。

我也面临同样的问题,经过一些互联网搜索和调试,我发现当你在第一次关闭后尝试打开第二个内容对话框时,你会收到此错误。 这是因为内容对话框始终是异步显示的,并且不会等待前一个正确关闭,从而引发exception。

解决方案:在打开第二个对话框之前使用Thread.Sleep(500) ,以便正确关闭上一个对话框。

注意: 500的睡眠时间不是强制性的。 您可以使用足以关闭第一个对话框的那个。

“一次只能打开一个ContentDialog”

这种说法并不完全正确。 您一次只能ShowAsync一个ContentDialog。 您需要做的就是在打开另一个ContentDialog之前隐藏它。 然后,在第二个ContentDailog的“等待ShowAsync”之后,您只需调用“var T = this.ShowAync()”来取消隐藏它。 例:

 public sealed partial class MyDialog2 : ContentDialog { ... } public sealed partial class MyDialog1 : ContentDialog { ... private async void Button1_Click(object sender, RoutedEventArgs e) { // Hide MyDialog1 this.Hide(); // Show MyDialog2 from MyDialog1 var C = new MyDialog2(); await C.ShowAsync(); // Unhide MyDialog1 var T = ShowAsync(); } }