Reputation: 348
My ViewModel has a 30 second data refresh service delegate method:
public Task OnDataRefreshed(List<MyType> data)
{
this.Data = data;
LongRunningGetDetailsAsync();
return Task.FromResult(0);
}
Public property Data
is displayed and refreshed in the view properly.
The intention here is not to await the async task (fire-and-forget) LongRunningGetDetailsAsync()
as it will introduce a significant delay before the Data
is displayed if executed sync. I want to show Data
ASAP and then let async task fetch the details at its own pace and let the view binding catch up then.
private async Task LongRunningGetDetailsAsync()
{
foreach (MyType dataitem in this.Data)
{
dataitem.Details = await _apiEndpointService.GetDetails(dataitem.Id);
}
}
LongRunningGetDetailsAsync()
is where the binding is not firing. I set a break point at the end of LongRunningGetDetailsAsync
watching Data.Details - the Data.Details are there, but it is never displayed in the view.
Thank you in advance for your time!
EDIT: Changed to
public async Task OnDataRefreshed(ObservableCollection<MyType> data)
{
this.Data = data;
await LongRunningGetDetailsAsync();
}
Data
is bound to Mvx.MvxListView
. If the list is long and an item happens to be out of view, once scrolled to, it displays the updated model OK. "Data":
public class MyType
{
public string MyProperty { get; set; }
public string Details { get; set; }
}
private ObservableCollection<MyType> _data;
public ObservableCollection<MyType> Data
{
get { return _data; }
set
{
if (SetProperty(ref _data, value))
{
RaisePropertyChanged(() => Data);
}
}
}
View binding:
<Mvx.MvxListView
local:MvxBind="ItemsSource Data"
local:MvxItemTemplate="@layout/listitem"
... />
listitem:
<TextView local:MvxBind="Text MyProperty" ...
<TextView local:MvxBind="Text Details" ...
Upvotes: 0
Views: 652
Reputation: 11635
Since you're changing the Details
property you need to let the view know that it has changed. You would need to use the same logic as you do for your Data
property:
private string _details;
public string Details
{
get { return _details; }
set
{
if (SetProperty(ref _details, value))
{
RaisePropertyChanged(() => Details);
}
}
}
As a side note, try to avoid setters for your lists. In the future you may have other logic connected to your lists which, when overwritten, just complicates things. Instead, since it is exposed as an ObservableCollection<T>
you can call Clear
and then Add
on the value from the getter.
Upvotes: 0
Reputation: 15253
First, use await
keyword when you're calling your function and mark your function as async
.
public async Task OnDataRefreshed(List<MyType> data)
{
this.Data = data;
await LongRunningGetDetailsAsync();
}
Now as I understand, you want to show items in your UI as soon as you get each of them. If your bindings are correct, the changes above should do what you need. You should probably use ObservableCollection<>
instead of List<>
for Data
property though.
Upvotes: 1