PCL中的MVVMCross异步和等待方法

时间:2014-08-19 11:28:05

标签: c# xamarin

我对MvxSpinner和ViewModel的绑定有点问题。它似乎没有在我的微调器中显示任何数据。

我的ViewModel调用一个实际返回数据的服务,这样我可以填充我的ViewModel,然后我的ViewModel填充我的View。

问题是我的服务调用是异步的,在我看来,当我的服务仍在尝试获取数据时,视图首先被加载。

这一切都发生在我的View加载时,因此微调器绑定到我的ViewModel。在我决定使服务异步之前,这确实有效。如何确保我的视图获取最新的ViewModel数据?

这是我的ViewModel

public class HomeViewModel
    : MvxViewModel
{

    string PracticeName = string.Empty;

    private readonly IMvxMessenger _messenger;
    private readonly IHomeService _homeService;
    public HomeViewModel(IHomeService homeService, IMvxMessenger messenger)
    {
        _homeService = homeService;
        _messenger = messenger;
        GetPractice ();
        _homeService.GetReportList(this);
    }

    public HomeViewModel()
    {

    }


    private async void GetPractice()
    {
        try 
        {
            _practiceItems = await _homeService.GetPracticeList(this);
        } 
        catch (Exception ex) 
        {
            //return null;
        }
    }

    public class Practices
    {
        public string ErrorMessage { get; set; }

        public List<string> Practice { get; set; }
    }

    private List<string> _practiceItems;
    public List<string> PracticeItems
    {
        get { return _practiceItems; }
        set { _practiceItems = value; RaisePropertyChanged(() => PracticeItems); }
    }
}

这是我的服务

public class HomeService : IHomeService
{
    public HomeService()
    {

    }

    public async Task<List<string>> GetPracticeList(HomeViewModel viewModel)
    {
        HomeViewModel.Practices rootobject = null;
        var client = ClientHandler.Client;

        client.BaseAddress = new Uri("http://10.1.20.106/sdf");

        HttpResponseMessage msg = await client.GetAsync (string.Format ("api/practice?username={0}", ClientHandler.Username));
        if(msg.IsSuccessStatusCode)
        {
            var res = await msg.Content.ReadAsStringAsync();
            rootobject = JsonConvert.DeserializeObject<HomeViewModel.Practices>(res);
            if (!string.IsNullOrEmpty (rootobject.ErrorMessage)) 
            {
                return null;
            }
            //return rootobject.Practice;
        }

        return rootobject.Practice;
    }   
}

另请注意,此视图仅在上一个视图单击按钮导航到此视图后才会出现。

2 个答案:

答案 0 :(得分:3)

请在RaisePropertyChanged关键字后强行拨打await

private async void GetPractice()
{
    try 
    {
        _practiceItems = await _homeService.GetPracticeList(this);
        RaisePropertyChanged(() => PracticeItems); 
    } 
    catch (Exception ex) 
    {
        //return null;
    }
}

答案 1 :(得分:0)

我认为,现代的方法(至少从第5个主要版本开始)是(1)在属性设置程序中使用 SetProperty()基类的方法设置属性支持字段值, (2)使用设置属性值的代码覆盖 async Initialize()

private List<string> _practiceItems;
public List<string> PracticeItems
{
    get => _practiceItems;
    set => SetProperty(ref _practiceItems, value);
}

public override async Task Initialize()
{
    await base.Initialize();        
    PracticeItems = await _homeService.GetPracticeList(this);
}

此方法的好处是,如果新值与当前值不同,则SetProperty()会处理NotifyPropertyChanged,并且您使用适当的位置来调用async方法(因为调用该方法绝对不是一种好习惯)构造函数的异步方法)。