2012-10-04 17 views
23

Próbuję zaimplementować okno dialogowe spróbuj ponownie/anuluj w oknach 8. Okno dialogowe pokazuje dobrze za pierwszym razem, ale po kliknięciu spróbuj ponownie i ponownie nie, otrzymam wyjątek odmowy dostępu po wywołaniu ShowAsync. Nie wiem dlaczego, ale czasami dziwne, że kod działa dobrze i nie dostaję wyjątku, kiedy umieszczam punkty przerwania. naprawdę niezorientowany tutajMessageDialog ShowAsync zgłasza wyjątek accessdenied w drugim oknie dialogowym

tutaj jest kod.

async void DismissedEventHandler(SplashScreen sender, object e) 
    { 
     dismissed = true; 
     loadFeeds(); 
    } 
    private async void loadFeeds() 
    { 
     await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => 
     { 
      try 
      { 
       RSSDataSource rssDataSource = (RSSDataSource)App.Current.Resources["RSSDataSource"]; 
       if (rssDataSource != null) 
       { 
        await rssDataSource.DownloadFeeds(); 
        await rssDataSource.GetFeedsAsync(); 
       } 

       AdDataSource ads = (AdDataSource)App.Current.Resources["AdDataSource"]; 

       if (ads != null) 
       { 
        await ads.DownloadAds(); 
       } 
       rootFrame.Navigate(typeof(HomePageView)); 

       Window.Current.Content = rootFrame; 
      } 
      catch 
      { 
       ShowError(); 
      } 

     }); 
    } 
    async void ShowError() 
    { 
     // There was likely a problem initializing 
     MessageDialog msg = new MessageDialog(CONNECTION_ERROR_MESSAGE, CONNECTION_ERROR_TITLE); 

     // Add buttons and set their command handlers 
     msg.Commands.Add(new UICommand(COMMAND_LABEL_RETRY, new UICommandInvokedHandler(this.CommandInvokedHandler))); 
     msg.Commands.Add(new UICommand(COMMAND_LABEL_CLOSE, new UICommandInvokedHandler(this.CommandInvokedHandler))); 
     // Set the command to be invoked when a user presses 'ESC' 
     msg.CancelCommandIndex = 0; 

     await msg.ShowAsync(); 
    } 

    /// <summary> 
    /// Callback function for the invocation of the dialog commands 
    /// </summary> 
    /// <param name="command">The command that was invoked</param> 
    private void CommandInvokedHandler(IUICommand command) 
    { 
     string buttonLabel = command.Label; 
     if (buttonLabel.Equals(COMMAND_LABEL_RETRY)) 
     { 
      loadFeeds(); 
     } 
     else 
     { 
      // Close app 
      Application.Current.Exit(); 
     } 
    } 

Odpowiedz

24

Ok znalazłem szybkiego rozwiązania,

zdefiniować klasę IAsyncOperation varialble

IAsyncOperation<IUICommand> asyncCommand = null; 

i ustawić go do sposobu ShowAsync z MessageDialog

asyncCommand = msg.ShowAsync(); 

W obsługi poleceń dla ponownej próby/spróbuj ponownie sprawdź, czy asyncCommand nie jest null i anuluj ostatnią operację, jeśli to konieczne:

if(asyncCommand != null) 
{ 
    asyncCommand.Cancel(); 
} 

Proszę, pozwól mi, jeśli jest lepsze podejście do tego.

+0

Aby zapobiec coraz "Użyj nieprzypisanych zmiennej lokalnej 'asyncCommand'", miałem na przypisanie null do asyncCommand po przypisaniu. –

+1

Uwaga boczna: Miałem własne uruchamianie zadań w jednym wątku i robiłem JEDEN showAsync z JEDNEGO wątku naraz. Wygląda na to, że jeśli jedna ShowAsync kończy się w klatce 1, a druga ShowAsync rozpoczyna się w klatce 2, może pojawić się losowy błąd odmowy dostępu: /. Ręczne anulowanie jednak działa. – RelativeGames

+0

@clay Zaktualizowałem kod powyżej – Syler

3

Istnieje odpowiedź na to na forach MSDN, które mogą ci w tym pomóc.

http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/c2f5ed68-aac7-42d3-bd59-dbf2673dd89b

Mam podobny problem, ale moje rozmowy showAsync są w oddzielnych funkcji na oddzielnych wątków, więc nie mogę upuść zrobić() tam nie sądzę ...

+1

spróbuj użyć zmiennej instancji i przytrzymaj odwołanie do polecenia asyncCommand i sprawdź, czy polecenie nie ma wartości null. to może zadziałać. – Syler

+1

Tak, to działa w moim przypadku. Wydaje się być masywnym hakerem, chociaż jest to –

3

Kilka dni temu spotkałem się z tym samym problemem i rozwiązałem go, czekając na ShowAsync, a następnie wykonując wywołanie rekursywne, które ponownie otworzy MessageDialog.

public async void ShowDlg(){ 
    Action cmdAction = null; 
    var msgDlg = new MessageDialog("Content.", "Title"); 
    msgDlg.Commands.Add(new UICommand("Retry", (x) => { 
    cmdAction =() => ShowDlg(); 
    })); 
    msgDlg.Commands.Add(new UICommand("Cancel", (x) => { 
    cmdAction =() => <Action associated with the cancel button>; 
    })); 
    msgDlg.DefaultCommandIndex = 0; 
    msgDlg.CancelCommandIndex = 1; 

    await msgDlg.ShowAsync(); 
    cmdAction.Invoke(); 
} 

Mam nadzieję, że ta pomoc!

9

Jestem późno do partii, ale tutaj jest to sposób, w którym można zawsze czekają na wynik w oknie dialogowym, a także nie trzeba się martwić o wywołanie zbyt wiele w jednym rzędzie:

najpierw zdefiniować statyczną zmienna i metoda w aplikacji:

private static IAsyncOperation<IUICommand> messageDialogCommand = null; 
public async static Task<bool> ShowDialog(MessageDialog dlg) { 

    // Close the previous one out 
    if (messageDialogCommand != null) { 
     messageDialogCommand.Cancel(); 
     messageDialogCommand = null; 
    } 

    messageDialogCommand = dlg.ShowAsync(); 
    await messageDialogCommand; 
    return true; 
} 

Teraz można przekazać w dowolnym oknie dialogowym i zawsze oczekiwać na wykonanie. To dlatego zwraca wartość bool zamiast pustą. Nie musisz się martwić kolizjami między wielokrotnościami. Dlaczego ta metoda nie zaakceptuje ciągu? Ze względu na tytuł i narzędzia obsługi poleceń Tak/Nie, które można przypisać do określonego okna dialogowego, którego używasz.

Invoke takich jak:

await App.ShowDialog(new MessageDialog("FOO!")); 

lub

var dlg = new MessageDialog("FOO?", "BAR?"); 
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(YesHandler))); 
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler(NoHandler))); 
await App.ShowDialog(dlg); 
2

Innym rozwiązaniem:

private bool _messageShowing = false; 

// ... 

if (!_messageShowing) 
{ 
    _messageShowing = true; 
    var messageDialog = new MessageDialog("Example"); 

    // ... "messageDialog" initialization 

    Task<IUICommand> showMessageTask = messageDialog.ShowAsync().AsTask(); 
    await showMessageTask.ContinueWith((showAsyncResult) => 
     { 
      _messageShowing = false; 
     }); 
} 
+0

Thx! to jedyne rozwiązanie, które działa dla mnie! –