ventanas ventana permitir internet habilitar extension emergentes emergente desbloquear como chrome bloquear activar c# windows-8 popup windows-runtime winrt-async

c# - internet - ¿Cómo permitir múltiples ventanas emergentes a la vez en WinRT?



pop ups chrome (2)

Si llama al comando ShowAsync en un objeto MessageDialog cuando otro objeto MessageDialog ya se ha mostrado al usuario pero no se ha descartado (es decir, muestra una ventana emergente cuando ya hay otro), se lanza una ShowAsync UnauthorizedAccessException . Esto puede dificultar las cosas cuando tienes varios hilos que intentan alertar al usuario al mismo tiempo.

Mi solución actual (stopgap) es simplemente rodear la llamada ShowAsync con un bloque try / catch y tragar la excepción. Esto conduce indeseablemente a que el usuario pierda notificaciones posteriores. La única otra forma de evitar esto que puedo pensar es implementar manualmente algún tipo de cola emergente. Esto parece una cantidad desmesurada de trabajo, sin embargo, teniendo en cuenta que otros marcos (como Windows Phone) no tienen este problema, simplemente mostrarán las ventanas emergentes una tras otra cuando el usuario las descarte.

¿Hay alguna otra manera de resolver este problema?


Puede hacerlo fácilmente con este método de extensión:

public static class MessageDialogShower { private static SemaphoreSlim _semaphore; static MessageDialogShower() { _semaphore = new SemaphoreSlim(1); } public static async Task<IUICommand> ShowDialogSafely(this MessageDialog dialog) { await _semaphore.WaitAsync(); var result = await dialog.ShowAsync(); _semaphore.Release(); return result; } }


Hay muchas maneras de abordarlo y la elección puede depender de sus habilidades, requisitos y preferencias.

Mi elección personal es evitar el uso de cuadros de diálogo porque son malos para la experiencia del usuario ( mal ). Hay entonces soluciones alternativas como mostrar una pantalla / página separada con la IU que requiere que el usuario proporcione alguna entrada cuando realmente se requiera o mostrar una ventana emergente no modal en algún lugar en el lateral / borde / esquina si la entrada del usuario es opcional y ocultarla después de un momento u otro tipo de notificación que no interrumpe el flujo de usuarios.

Si no está de acuerdo o no tiene el tiempo, los recursos o las habilidades para implementar una alternativa, puede crear una especie de envoltorio alrededor de la llamada a MessageDialog.ShowAsync () para hacer cola o ignorar nuevas solicitudes mientras ya se muestra un cuadro de diálogo.

Esta clase tiene métodos de extensión que permiten ignorar una nueva solicitud de espectáculo cuando ya se muestra otro diálogo o poner en cola las solicitudes:

/// <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); } }

Prueba

// 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();