I am trying to use a CollectionView that gets bound to some data loaded from an external API. I am using the MVVM toolkit to create Observable properties in my ViewModel.
<CollectionView x:Name="collectionView"
ItemsSource="{Binding MyCollection}"
SelectionMode="None"
HorizontalOptions="FillAndExpand">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" ItemSpacing="8" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:MyModel">
<Border>
<VerticalStackLayout>
...snip
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<Label Text="Placeholder for empty collection" />
</CollectionView.EmptyView>
</CollectionView>
My ViewModel looks something like this.
public partial class MyViewModel : ObservableObject
{
private readonly IApiClient apiClient;
[ObservableProperty]
private IEnumerable<MyModel>? myCollection;
public TripListViewModel(IApiClient apiClient)
{
this.apiClient= apiClient;
}
[RelayCommand]
public async Task RefreshDataAsync(CancellationToken cancellationToken = default)
{
//delay is for debugging purposes
await Task.Delay(3000);
IEnumerable<MyModel> data = await apiClient.GetDataAsync();
this.MyCollection = data;
}
}
Code Behind:
public partial class MyPage : ContentPage
{
private readonly MyViewModel viewModel;
public MyPage (MyViewModel viewModel)
{
this.viewModel = viewModel;
this.BindingContext = viewModel;
InitializeComponent();
}
protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
base.OnNavigatedTo(args);
Task.Run(async () =>
{
await viewModel.RefreshDataAsync();
});
}
}
When I run this, I can see the Empty Collection message for 3 seconds ("Placeholder for empty collection"), but then the Content of the CollectionView disappears entirely.
If I set a background color on the CollectionView, I can see that it is taking up space, but no items are rendering inside of it.
Things I have tried that didn't work.
- Assigning
MyCollectionfrom the UI thread. - Calling
RefreshDataAsyncinOnAppearingandOnBindingContextChanged - Not wrapping the call to
RefreshDataAsyncwithTask.Run - Verfied that
GetDataAsyncis returning items (about 30) - Set
MinimumHeightRequeston the<Border>
I've only observed this issue on Windows. To make it more worse, it occasionally works! On roughly 3/4 runs, I see nothing in the CollectionView, but about 1/4 of the time, the ColectionView renders correctly. This tells me that it might be some sort of race condition, but I don't see it.