Xamarin.Forms Page.DisplayAlert dans Page.OnAppearing


Bondoline

Je ne parviens pas à DisplayAlertafficher une fenêtre contextuelle dans le OnAppearingrappel d'un Xamarin.Forms Page. Voici ce que j'ai essayé jusqu'à présent :

protected override void OnAppearing()
{
    base.OnAppearing();

    this.DisplayAlert("Alert", "Consider yourself alerted", "OK");
}

Considérant qu'il DisplayAlerts'agit techniquement d'une asyncfonction, renvoyant un Task, j'ai également essayé ce qui suit :

protected async override void OnAppearing()
{
    base.OnAppearing();

    await this.DisplayAlert("Alert", "Consider yourself alerted", "OK");
}

Cependant, ni l'un ni l'autre ne semble fonctionner. Je suppose que cela n'a pas vraiment de sens de faire OnAppearingcomme étant asyncdu tout, car il ne renvoie pas un Task, et cela se transforme donc en une situation de feu et d'oubli en ce qui concerne le cadre d'appel. Il en va de même par extension DisplayAlertdans ce contexte. Donc , d'une part , je ne pense pas vraiment que cela fonctionne du tout, mais si je me trompe, est - il possible d'utiliser DisplayAlertdans OnAppearing?

Mettre à jour

Il semble que je n'ai pas réussi à fournir un certain contexte. Je travaille à partir d'un modèle Shell Xamarin.Forms ; bien que j'en ai déjà développé quelques-uns après le modèle initial, il est donc difficile de dire à ce stade dans quelle mesure le Shell lui-même y contribue. De plus, ma plate-forme cible principale est Android.

Cela étant dit, j'ai pu démarrer un modèle d'application vierge et essayer le code ci-dessus dans le code autrement frais MainPage- les deux ont bien fonctionné. Je ne sais toujours pas pourquoi ils ne fonctionnent pas dans mon contexte d'application réel, je vais donc creuser là-bas et rendre compte de toutes les conclusions.

Bondoline

J'ai poussé ma petite expérience un peu plus loin et j'ai essayé l'application de modèle Shell de base.

L'ajout de l'exemple de DisplayAlertcode OP au code principal principal ItemsPagen'a pas fonctionné. Si j'ai fait ça,

protected async override void OnAppearing()
{
    base.OnAppearing();

    if (viewModel.Items.Count == 0)
        viewModel.LoadItemsCommand.Execute(null);

    await this.DisplayAlert("Alert", "Consider yourself alerted", "OK");
}

les éléments se chargeraient mais aucune boîte de dialogue ne s'afficherait. Si à la place j'ai déplacé la boîte de dialogue vers le haut,

protected async override void OnAppearing()
{
    base.OnAppearing();

    await this.DisplayAlert("Alert", "Consider yourself alerted", "OK");

    if (viewModel.Items.Count == 0)
        viewModel.LoadItemsCommand.Execute(null);
}

la boîte de dialogue ne s'afficherait pas et les éléments ne se chargeraient pas. Ainsi, l'exécution asynchrone est morte et/ou s'est égarée dans le grand seau dans le ciel.

J'ai ensuite essayé d'ajouter l' DisplayAlertéchantillon à la AppShellpage principale , seulement pour constater que le OnAppearingremplacement n'est pas du tout appelé pour la Shellclasse. Cela a été confirmé par le problème Shell ouvert suivant : [Bug] Shell - OnAppearing n'exécute pas #6486 .

Enfin, juste pour finir, j'ai essayé de pirater un appel à DisplayAlertdans le rappel asynchrone exécuté par LoadItemsCommandin ItemsPage.OnAppearing. Un peu méchant car cela passe la vue dans le modèle de vue, ce qui va directement à l'encontre du bon MVVM en premier lieu --

async Task ExecuteLoadItemsCommand(ItemsPage view)
{
    if (IsBusy)
        return;

    IsBusy = true;

    try
    {
        Items.Clear();
        var items = await DataStore.GetItemsAsync(true);
        foreach (var item in items)
        {
            Items.Add(item);
        }

        await Device.InvokeOnMainThreadAsync(async () =>
            await view.DisplayAlert("Alert", "Consider yourself alerted", "OK"));
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex);
    }
    finally
    {
        IsBusy = false;
    }
}

Ne me lapide pas.

Cela ne semblait pas avoir de meilleurs résultats. Tout comme lors de l'appel DisplayAlertdirect dans la page OnAppearing, l'exécution a juste pris une pause déjeuner. Le spinner lié au IsBusydrapeau ne s'est jamais arrêté, ce qui indique que le finallybloc n'a même jamais été exécuté.

Ma compréhension générale à ce stade est qu'il existe actuellement une certaine limitation dans le type d'opérations asynchrones qui peuvent être effectuées à partir d'un shell ContentPage. Même l' awaitappel ed à DataStore.GetItemsAsyncn'est pas vraiment asynchrone dans cette implémentation, donc je doute un peu que cela fonctionnerait réellement avec une connexion réelle et asynchrone à la base de données. J'ai pu DisplayAlerttravailler dans le contexte d'un gestionnaire d'événements normal, donc je pense que le problème est limité à la logique d'initialisation qui se déroule pendant OnAppearinget à tout ce qu'il finit par appeler ou planifier directement. Une grande partie de cela ne sont que des spéculations d'observation, mais je peux transmettre cela comme un bogue, à moins que quelqu'un puisse offrir une analyse plus complète.

Mise à jour (pour clôture, TOC, documentation, etc.)

Comme l'indiquent les commentaires, la version de Xamarin.Forms que j'utilisais (4.2.0) avait un bogue qui a été corrigé dans les versions ultérieures.

Articles connexes