在我的Xamarin.Forms
pcl项目中,我有一个xaml
页面label
。我希望在label
之后更新async task
。在我的ViewModel constructor
中,我为label
设置了默认文字。并创建一个名为async Task
的{{1}}函数。
问题1:我在哪里可以调用SomeTask()
函数。无法在SomeTask()
中调用async Task
功能。
问题2:如何在constructor
功能之后更新Label
文字。
我的代码:
async Task SomeTask()
答案 0 :(得分:1)
我建议您使用my NotifyTask
type;它在我的MSDN article on asynchronous MVVM data binding中描述,我认为这是最简单的方法:
public class MyPageViewModel : ViewModelBase
{
private NotifyTask<string> _selectedText;
public NotifyTask<string> SelectedText => _selectedText;
public MyPageViewModel()
{
_selectedText = NotifyTask.Create(SomeTask(), "Welcome");
}
private async Task<string> SomeTask()
{
await Task.Delay(3000);
return "Thanks";
}
}
然后,您的数据绑定将更改为绑定到SelectedText.Result
以显示“欢迎”,然后显示“谢谢”。数据绑定还有其他NotifyTask<T>
属性,例如IsNotCompleted
,IsCompleted
和ErrorMessage
,它们允许您通过数据绑定处理故障情况。
如果您不想使用此类型,您可以自己做类似的事情:
public class MyPageViewModel : ViewModelBase
{
private string _selectedText;
public string SelectedText
{
get { return _selectedText; }
set
{
if (_selectedText != value)
{
_selectedText = value;
RaisePropertyNotifyChanged(); // However you're doing this.
}
}
}
public MyPageViewModel()
{
_selectedText = "Welcome";
var _ = RunSomeTask();
}
private async Task RunSomeTask()
{
try
{
SelectedText = await SomeTask();
}
catch (Exception ex)
{
// TODO: Handle the exception.
// It *must* be handled here, or else it will be silently ignored!
}
}
private async Task<string> SomeTask()
{
await Task.Delay(3000);
return "Thanks";
}
}
构造函数启动RunSomeTask
操作,然后显式忽略其结果(请注意,这意味着将忽略所有异常)。 RunSomeTask
负责运行SomeTask
并处理其结果(和例外)。结果仅用于更新SelectedText
,并且会根据您认为适合您的应用的情况处理异常。
答案 1 :(得分:0)
怎么样
public MyPageViewModel()
{
_selectedText = "Welcome"; //Default text
SomeTask().ContinueWith(previousTask => SelectedText = previousTask.Result);
}
答案 2 :(得分:0)
什么是someTask
?即,应该从哪里调用?出于什么原因?这里需要上下文来了解调用函数可以接受的内容。该功能应该在页面的负载上运行吗?它可以晚点运行吗?如何通过用户输入调用?
我建议你可以调用一个静态方法,例如:
public static async Task<T> someTask() {
Console.WriteLine("Asynchronous method called.");
}
然后,您可以从多个地方拨打此电话。这严格取决于需要调用方法的位置/时间。它可能位于Load
事件处理程序中,以及其他位置。
答案 3 :(得分:0)
您可以创建异步工厂方法并使构造函数成为私有。然后,您调用该方法来创建MyPageViewModel
的实例。在该方法中,您可以调用string str = await SomeTask
public class MyPageViewModel : ViewModelBase
{
public async MyPageViewModel CreateAsync()
{
var model = new MyPageViewModel();
SelectedText = await SomeTask();
return model;
}
private MyPageViewModel ()
{
_selectedText = "Welcome"; //Default text
}
private Task<string> SomeTask()
{
return Task.Run(async () =>
{
await Task.Delay(3000); //Dummy task. It will return the status of Task.
return "Thanks"; //Update Text
});
}
}
所以不要像这样创建你的模型:
var model = new MyPageViewModel();
您可以像这样创建:
var model = await MyPageViewModel.CreateAsync();
答案 4 :(得分:0)
问题1:
使用委托和事件。
创建代表&amp;相关事件:
private delegate void MyDelegate();
private event MyDelegate myEvent;
在构造函数中订阅该事件:
myEvent += async () => await SomeTask();
在任何需要的地方执行活动:
myEvent(); //Note: Check the event for null, before executing
问题2:
如果在非UI线程上,则:
使用一些框架类来执行UI操作:例如 - Xamarin提供Device.BeginInvokeOnMainThread
我们可能总是将DataBinding与Label一起使用,并且只使用事件订阅更新ViewModel中的Binding Path值。
string _message;
public string Message
{
get => _message;
set
{
_message = value;
}
}
myEvent += () => Message = "New Value";
<Label Text = "{Binding Message}"/>