首页 > 解决方案 > Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert

问题描述

我无法在Xamarin.FormsDisplayAlert的回调中显示弹出窗口。这是我到目前为止所尝试的:OnAppearingPage

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

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

考虑到DisplayAlert技术上是一个async函数,返回 a Task,我还尝试了以下方法:

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

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

但是,两者似乎都不起作用。OnAppearing我的猜测是,它根本没有多大意义async,因为它不返回 a Task,所以这变成了关于调用框架的即发即弃的情况。DisplayAlert在这种情况下,同样的扩展也适用。所以一方面我真的不希望这会起作用,但万一我错了,是否可以使用DisplayAlertin OnAppearing

更新

似乎我未能提供一些背景信息。我正在使用 Xamarin.Forms Shell 模板;虽然我已经开发了一些超出初始模板的内容,但目前很难说 Shell 本身在多大程度上做出了贡献。另外,我的主要目标平台是Android。

话虽如此,我能够启动一个空白的应用程序模板并在其他新鲜的情况下尝试上面的代码MainPage——两者都工作得很好。我仍然不知道为什么它们在我的实际应用程序环境中不起作用,所以我将在那里进行一些挖掘并报告任何发现。

标签: c#androidxamarin.formsasync-awaitdialog

解决方案


让我的小实验更进一步,并尝试了基本的 Shell 模板应用程序。

将 OP 示例DisplayAlert代码添加到主代码ItemsPage隐藏中不起作用。如果我这样做,

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根本没有调用覆盖Shell。以下打开的 Shell 问题证实了这一点: [Bug] Shell - OnAppearing not execution #6486

最后,作为最后的延伸,我尝试将调用入侵到inDisplayAlert执行的异步回调LoadItemsCommandItemsPage.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. 在这个实现中,即使对awaited 的调用DataStore.GetItemsAsync也不是真正的异步,所以我有点怀疑它在给定一个真正的异步数据库连接的情况下是否真的有效。我已经能够DisplayAlert在普通事件处理程序的上下文中工作,所以我认为这个问题的范围是任何初始化逻辑在期间发生的OnAppearing任何事情,以及它最终直接调用或调度的任何事情。其中大部分只是观察性推测,但我可能会将其作为错误转发,除非有人可以提供更完整的分析。

更新(用于关闭、强迫症、文档等)

正如评论所示,我使用的 Xamarin.Forms 版本 (4.2.0) 有一个错误,该错误已在更高版本中修复。


推荐阅读