我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<bool>();
}
else ActiveDialog.Hide();
}
ActiveDialog = Dialog;
ActiveDialog.Closed += ActiveDialog_Closed;
await ActiveDialog.ShowAsync();
ActiveDialog.Closed -= ActiveDialog_Closed;
}
public static ContentDialog ActiveDialog;
static TaskCompletionSource<bool> DialogAwaiter = new TaskCompletionSource<bool>();
private static void ActiveDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args) { DialogAwaiter.SetResult(true); }
}
Run Code Online (Sandbox Code Playgroud)
要使用这些方法,您需要在变量中创建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);
Run Code Online (Sandbox Code Playgroud)
William Bradley 的上述方法很好。只是为了稍微完善一下,这里有一个扩展方法来提交并等待内容对话框的显示;该对话框将在所有其他已提交的内容对话框之后显示。注意:当用户单击之前积压的对话框时,您可能不再希望显示已提交的对话框;为了表明这一点,您可以传递一个谓词,该谓词将在其他对话框被关闭后进行测试。
static public class ContentDialogExtensions
{
static public async Task<ContentDialogResult> EnqueueAndShowIfAsync( this ContentDialog contentDialog, Func<bool> predicate = null)
{
TaskCompletionSource<Null> currentDialogCompletion = new TaskCompletionSource<Null>();
TaskCompletionSource<Null> 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<Null> PreviousDialogCompletion = null;
}
Run Code Online (Sandbox Code Playgroud)
另一种方法可能是使用 SemaphoreSlim(1,1)。
任何时候只能打开一个 ContentDialog。
这是事实。(我真的很惊讶,但只是一瞬间)你在任何时候都不能有多个对话框,这更像是微软的指导方针,因为多个对话框彼此叠在一起填充内容真的很混乱。
尝试更改您的用户体验以仅显示一个复杂的ContentDialog,而对于所有其他消息,请使用MessageDialog - 它支持多个按钮(手机上只有两个,但桌面上有更多)用于用户响应,但没有复选框或类似的“智能”内容。
就我而言,MessageDialogs 确实很有帮助,但在某些区域我使用了链式ContentDialogs,但为此你必须 等待第一个对话框,然后立即打开第二个对话框,没有任何例外。在您的情况下,当您尝试打开下一个时,ContentDialog 似乎未完全关闭。
希望能帮助到你!