Провел мой небольшой эксперимент еще на один шаг и попробовал приложение 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) была ошибка, которая была исправлена в более поздних версиях.