Xamarin表单在等待时改变按钮的文本

本文关键字:按钮 文本 改变 表单 在等待 Xamarin | 更新日期: 2023-09-27 18:17:24

我正在使用Xamarin Forms开发一个跨平台应用程序。

我想改变按钮"做某事"的文本类似于"等待",而代码正在处理例程,并回到"做某事"后,代码完成运行。

问题是:按钮文本只有在代码完成后才会改变。

简单的例子:

private void Button_Clicked(object sender, EventArgs e)
{
    var btn = (Button)sender;
    btn.Text = "Wait";
    ...some code..
    btn.Text = "Do Something";
}

在代码完成之前,有一些方法可以"强制"文本更新为"等待"?

Xamarin表单在等待时改变按钮的文本

    private async void Btn1_Clicked(object sender, EventArgs e)
    {
       btn1.Text = "Wait";
        await Task.Run(async () =>
        {
            for (int i = 1; i <= 5; i++)
            {
                //if your code requires UI then wrap it in BeginInvokeOnMainThread
                //otherwise just run your code
                Device.BeginInvokeOnMainThread(() =>
                {
                    btn1.Text = $"Wait {i}";
                });
                await Task.Delay(1000);
            }
        });
        btn1.Text = "Done";

    }

主要的一点是,您需要等待的异步操作不会发生在ui线程上。Yuri的解决方案做到了这一点,但你也可以做你的异步操作,然后如果你需要对UI进行任何更新,你只需要在UI- thread上发生,以防止UI被锁定。

真正的问题来自你的线程是如何工作的。如果您想要实时查看,请打开Xamarin Stud中的Threads调试pad,并在逐步执行代码时查看线程。

让我们以你的代码为例:

private void Button_Clicked(object sender, EventArgs e)
{
    var btn = (Button)sender;
    btn.Text = "Wait";
    ...

当我们进入"Button_Clicked"事件处理程序时,我们现在处于ui线程中。我们怎么知道的?因为用户点击了按钮,我们在这里。一切都在主UI线程上运行。无论我们接下来在代码中做什么,都将继续在该线程上运行,除非操作系统出于某种原因(性能,这就是操作系统的工作方式等)决定它需要管理线程。

如果你的一些代码做一些异步任务,比如发送一个web请求调用从REST API获取一些数据,你需要知道你在哪个线程上。如果不手动处理,我们不能保证我们的web请求调用将在ui线程或任何线程上运行。这是我们先进的操作系统的好处,它为我们处理多核多线程处理。

出于这个原因,我们希望确保对UI的任何更新都发生在UI线程上。正确的代码解决方案如下:

private async void Btn1_Clicked(object sender, EventArgs e)
{
   var btn = (Button)sender;
   btn.Text = "Wait";
   ...some code...maybe async or not (take out async above if not)
   Device.BeginInvokeOnMainThread(() =>
   {
        btn.Text = "Do Something";
   });
}    

这对我们有效,因为我们正在告诉Xamarin。窗体以在主线程上运行该命令。Xamarin的。Forms以这种方式公开主UI-Thread。另一种选择是获取UI-Thread的上下文,并将其缓存以便在进行更新时使用。这是Xamarin中典型的操作。Android和Xamarin。iOS应用程序。

实现这一切的真正方法是通过数据绑定。Xamarin的。构建表单的目的是为了与模型-视图-视图模型(MVVM)模式一起使用。Xamarin的。当你调用OnPropertyChanged时,Forms Bindings会为你处理所有的上下文切换。这样你就可以在你的ViewModel中更新属性绑定到你的按钮文本。

我希望这有助于更好地理解线程级别上发生的事情!

披露:我为Xamarin/Microsoft工作

In Xamarin。表单使用这种方式

  Device.BeginInvokeOnMainThread(() =>
       {
      Task.Delay(4000).Wait();
            btn.Text = "Do Something";
       });