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";
}
在代码完成之前,有一些方法可以"强制"文本更新为"等待"?
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";
});