如何允许的WinRT一次为多个弹出窗口? [英] How to allow for multiple popups at once in WinRT?

查看:259
本文介绍了如何允许的WinRT一次为多个弹出窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果你调用一个 MessageDialog 对象的 ShowAsync 命令时,另一个 MessageDialog 对象已显示给用户,但没有被驳回(即你显示一个弹出时,另一个已经是),一个 UnauthorizedAccessException 被抛出。这可为难,当你有多个线程试图提醒在同一时间给用户。

If you call the ShowAsync command on a MessageDialog object when another MessageDialog object has already been displayed to the user but not dismissed (i.e. you show a popup when another one is already up), an UnauthorizedAccessException is thrown. This can make things difficult when you have multiple threads attempting to alert the user at the same time.

我目前(治标)解决方案仅仅是包围 ShowAsync 调用了try / catch块和吞咽异常。这不期望地导致了用户在随后通知错失。解决这个,我能想到的唯一的另一种方法是手动实现某种弹出队列。这似乎是工作的过多的,但考虑到其他框架(如Windows手机)没有这个问题,只会显示接连弹出一个作为用户消除它们。

My current (stopgap) solution is merely to surround the ShowAsync call with a try/catch block and swallow the exception. This undesirably leads to the user missing out on subsequent notifications. The only other way around this that I can think of is to manually implement some sort of popup queue. This seems like an inordinate amount of work, however, considering other frameworks (like Windows Phone) do not have this issue and will merely display the popups one after another as the user dismisses them.

有另一种方式来解决这个问题?

Is there another way to solve this problem?

推荐答案

有很多种方法来实现它,并选择可能取决于你的技能,要求和preferences。

There are many ways to approach it and the choice might depend on your skills, requirements and preferences.

我个人的选择是避免使用对话框完全因为他们是坏的用户体验(的邪恶)。有那么像的UI显示一个单独的屏幕/页面要求用户提供一些当它真正需要输入或侧面/ EDGE /转角的地方显示一个非模态弹出,如果用户输入的是可选的,隐藏它的替代解决方案片刻或一些其他形式的通知,不破坏用户流量之后。

My personal choice is to avoid using dialog boxes altogether since they are bad for user experience (evil). There are then alternative solutions like displaying a separate screen/page with the UI requiring user to provide some input when it really is required or displaying a non-modal popup somewhere on the side/edge/corner if the user input is optional and hiding it after a moment or some other sort of notification that doesn't break user flow.

如果您不同意或没有时间,资源或技能来实现一个选择 - 你可以建立某种形式的周围MessageDialog.ShowAsync的包装()的调用要么队列或忽略新的请求,就已经显示一个对话框

If you disagree or don't have the time, resources or skills to implement an alternative - you can create some sort of a wrapper around MessageDialog.ShowAsync() call to either queue or ignore new requests while a dialog is already shown.

本类有扩展方法允许或者当已经显示另一个对话框忽略了一个新节目请求或排队请求:

This class has extension methods to allow to either ignore a new show request when another dialog is already displayed or queue up the requests:

/// <summary>
/// MessageDialog extension methods
/// </summary>
public static class MessageDialogExtensions
{
    private static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;

    /// <summary>
    /// Begins an asynchronous operation showing a dialog.
    /// If another dialog is already shown using
    /// ShowAsyncQueue or ShowAsyncIfPossible method - it will wait
    /// for that previous dialog to be dismissed before showing the new one.
    /// </summary>
    /// <param name="dialog">The dialog.</param>
    /// <returns></returns>
    /// <exception cref="System.InvalidOperationException">This method can only be invoked from UI thread.</exception>
    public static async Task ShowAsyncQueue(this MessageDialog dialog)
    {
        if (!Window.Current.Dispatcher.HasThreadAccess)
        {
            throw new InvalidOperationException("This method can only be invoked from UI thread.");
        }

        while (_currentDialogShowRequest != null)
        {
            await _currentDialogShowRequest.Task;
        }

        var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
        await dialog.ShowAsync();
        _currentDialogShowRequest = null;
        request.SetResult(dialog);
    }

    /// <summary>
    /// Begins an asynchronous operation showing a dialog.
    /// If another dialog is already shown using
    /// ShowAsyncQueue or ShowAsyncIfPossible method - it will wait
    /// return immediately and the new dialog won't be displayed.
    /// </summary>
    /// <param name="dialog">The dialog.</param>
    /// <returns></returns>
    /// <exception cref="System.InvalidOperationException">This method can only be invoked from UI thread.</exception>
    public static async Task ShowAsyncIfPossible(this MessageDialog dialog)
    {
        if (!Window.Current.Dispatcher.HasThreadAccess)
        {
            throw new InvalidOperationException("This method can only be invoked from UI thread.");
        }

        while (_currentDialogShowRequest != null)
        {
            return;
        }

        var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
        await dialog.ShowAsync();
        _currentDialogShowRequest = null;
        request.SetResult(dialog);
    }
}

测试

// This should obviously be displayed
var dialog = new MessageDialog("await ShowAsync", "Dialog 1");
await dialog.ShowAsync();

// This should be displayed because we awaited the previous request to return
dialog = new MessageDialog("await ShowAsync", "Dialog 2");
await dialog.ShowAsync(); 

// All other requests below are invoked without awaiting
// the preceding ones to complete (dialogs being closed)

// This will show because there is no dialog shown at this time
dialog = new MessageDialog("ShowAsyncIfPossible", "Dialog 3");
dialog.ShowAsyncIfPossible();

// This will not show because there is a dialog shown at this time
dialog = new MessageDialog("ShowAsyncIfPossible", "Dialog 4");
dialog.ShowAsyncIfPossible();

// This will show after Dialog 3 is dismissed
dialog = new MessageDialog("ShowAsyncQueue", "Dialog 5");
dialog.ShowAsyncQueue();

// This will not show because there is a dialog shown at this time (Dialog 3)
dialog = new MessageDialog("ShowAsyncIfPossible", "Dialog 6");
dialog.ShowAsyncIfPossible();

// This will show after Dialog 5 is dismissed
dialog = new MessageDialog("ShowAsyncQueue", "Dialog 7");
dialog.ShowAsyncQueue();

// This will show after Dialog 7 is dismissed
dialog = new MessageDialog("ShowAsyncQueue", "Dialog 8");
dialog.ShowAsyncQueue();

这篇关于如何允许的WinRT一次为多个弹出窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆