我对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;
}
}
另请注意,此View仅在上一个View单击按钮导航到此视图后才会出现。
请在RaisePropertyChanged
关键字后强行拨打await
,如下所示。
private async void GetPractice()
{
try
{
_practiceItems = await _homeService.GetPracticeList(this);
RaisePropertyChanged(() => PracticeItems);
}
catch (Exception ex)
{
//return null;
}
}
我认为现代(至少从第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,并且您使用适当的位置来调用异步方法(因为调用异步方法绝对不是一个好习惯)构造函数)。