我的小实验更进一步,尝试了基本的 Shell 模板应用程序。
添加 OP 示例DisplayAlert
代码到mainItemsPage
代码隐藏不起作用。如果我这样做的话
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);
}
该对话框不会显示,也不会加载项目。因此,异步执行死了和/或溜进了天空中的大桶中。
然后我尝试添加DisplayAlert
样本到主要AppShell
页面,才发现OnAppearing
根本不会调用 overrideShell
班级。以下开放的 Shell 问题证实了这一点:[Bug] Shell - OnAppearing 未执行
第6486章 https://github.com/xamarin/xamarin.forms/issues/6486#.
最后,作为最后的努力,我尝试拨打电话DisplayAlert
进入异步回调执行LoadItemsCommand
in 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
块甚至从未被执行。
我目前的一般理解是,目前可以从 Shell 完成的异步操作类型存在一些限制。ContentPage
。即便是await
埃德致电DataStore.GetItemsAsync
在这个实现中并不是真正的异步,所以我有点怀疑它是否真的能在真正的异步数据库连接下工作。我已经能够得到DisplayAlert
在正常事件处理程序的上下文中工作,所以我认为问题的范围是在初始化逻辑期间发生的任何事情OnAppearing
以及它最终直接调用或调度的任何内容。其中大部分只是观察性猜测,但我可能会将其作为错误转发,除非有人可以提供更完整的分析。
Update(用于关闭、强迫症、文档等)
正如评论所示,我使用的 Xamarin.Forms 版本 (4.2.0) 有一个错误,该错误已在更高版本中修复。