Xamarin.Forms Page.DisplayAlert в Page.OnAppearing - PullRequest
0 голосов
/ 17 июня 2020

Я не могу получить всплывающее окно DisplayAlert для отображения в обратном вызове OnAppearing Xamarin.Forms Page. Вот что я пробовал до сих пор:

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

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

Учитывая, что DisplayAlert технически является функцией async, возвращающей Task, я также пробовал следующее:

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

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

Однако ни один из них не работает. Я предполагаю, что на самом деле не имеет большого смысла делать OnAppearing как async, так как он не возвращает Task, и поэтому это превращается в ситуацию «выстрелил и забыл» в отношении Вызов рамки. То же самое касается DisplayAlert в этом контексте. Так что, с одной стороны, я действительно не ожидаю, что это вообще сработает, но если я ошибаюсь, можно ли использовать DisplayAlert в OnAppearing?

Обновление

Кажется, я не смог предоставить какой-то контекст. Я работаю с шаблоном оболочки Xamarin.Forms; хотя я уже разработал кое-что, выходящее за рамки исходного шаблона, поэтому сейчас трудно сказать, в какой степени сама оболочка вообще вносит свой вклад. Кроме того, моя основная целевая платформа - Android.

При этом я смог запустить пустой шаблон приложения и попробовать приведенный выше код в sh MainPage - оба работали хорошо. Я до сих пор не знаю, почему они не работают в моем реальном контексте приложения, поэтому я собираюсь покопаться там и доложить о любых выводах.

1 Ответ

0 голосов
/ 17 июня 2020

Провел мой небольшой эксперимент еще на один шаг и попробовал приложение basi c Shell template.

Добавление кода OP-образца DisplayAlert в основной ItemsPage codebehind не сработало. Если бы я сделал это,

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

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

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

элементы загрузились бы, но диалоговое окно не отображалось. Если бы вместо этого я переместил диалоговое окно вверх,

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

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

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

, диалоговое окно не отображалось бы и элементы не загружались. Таким образом, выполнение asyn c умерло и / или ушло в большое ведро с большими битами в небе.

Затем я попытался добавить образец DisplayAlert на главную AppShell страницу, только чтобы найти переопределение OnAppearing вообще не вызывается для класса Shell. Это было подтверждено следующей открытой проблемой Shell: [Ошибка] Shell - OnAppearing не выполняется # 6486 .

Наконец, в качестве последнего этапа, я попытался взломать вызов DisplayAlert в обратный вызов asyn c, выполняемый LoadItemsCommand в ItemsPage.OnAppearing. Немного неприятно, так как он передает представление в модель представления, что, в первую очередь, прямо противоречит хорошему MVVM -

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

Не побивай меня камнями.

Это не было ' Похоже, результаты лучше. Так же, как при вызове DisplayAlert непосредственно в OnAppearing страницы, выполнение просто взяло перерыв на обед. Счетчик, связанный с флагом IsBusy, никогда не останавливался, что означает, что блок finally даже не был выполнен.

На данный момент я понимаю, что в настоящее время существует некоторое ограничение в типе asyn c операций, которые могут быть выполнены из ContentPage Shell. Даже вызов await ed к DataStore.GetItemsAsync не является действительно асинхронным в этой реализации, поэтому я несколько сомневаюсь, что он действительно сработает при реальном асинхронном подключении к базе данных. Мне удалось заставить DisplayAlert работать в контексте обычного обработчика событий, поэтому я думаю, что проблема ограничена любым логом инициализации c, происходящим во время OnAppearing, и тем, что он заканчивается прямым вызовом или планированием. По большей части это всего лишь предположения, основанные на наблюдениях, но я могу сообщить об этом как об ошибке, если только кто-то не сможет предложить более полный анализ.

Обновление (для закрытия, ОКР, документации и т. 1052 *)

Как видно из комментариев, в используемой мной версии Xamarin.Forms (4.2.0) была ошибка, которая была исправлена ​​в более поздних версиях.

...