UWP
ListView
ItemTemplate
ObservableCollection
Async

UWP not showing ListView.ItemTemplate since I changed from List to ObservableCollection and async

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When a UWP ListView.ItemTemplate stops showing after moving from List to ObservableCollection with async loading, the issue is usually binding lifecycle or threading, not the template itself. ObservableCollection is the right choice for dynamic updates, but only if updates happen on the UI thread and bindings are wired correctly. A structured diagnostic sequence resolves this quickly.

Why the Migration Can Break Rendering

List is static from XAML binding perspective, while ObservableCollection raises change notifications. After migration, common failure points are:

  • DataContext assigned too late
  • 'ItemsSource bound to wrong property'
  • collection replaced without property change notification
  • collection updated off UI thread after async completion

All four can produce an empty list even when data exists.

Correct ViewModel Pattern

Expose a stable ObservableCollection instance and populate it after async calls.

csharp
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3using System.Runtime.CompilerServices;
4using System.Threading.Tasks;
5
6public class MainViewModel : INotifyPropertyChanged
7{
8    public ObservableCollection<ItemVm> Items { get; } = new ObservableCollection<ItemVm>();
9
10    public async Task LoadAsync(IItemService service)
11    {
12        var rows = await service.GetItemsAsync();
13
14        Items.Clear();
15        foreach (var row in rows)
16            Items.Add(row);
17    }
18
19    public event PropertyChangedEventHandler PropertyChanged;
20    private void OnPropertyChanged([CallerMemberName] string name = null)
21        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
22}

Keeping one collection instance avoids rebinding problems.

XAML Binding Setup

Verify ItemsSource and template bindings first.

xml
1<ListView ItemsSource="{Binding Items}">
2    <ListView.ItemTemplate>
3        <DataTemplate>
4            <StackPanel>
5                <TextBlock Text="{Binding Title}" />
6                <TextBlock Text="{Binding Subtitle}" />
7            </StackPanel>
8        </DataTemplate>
9    </ListView.ItemTemplate>
10</ListView>

Misspelled property names in template bindings often produce blank rows with no obvious exception.

DataContext Timing in Page Lifecycle

Set DataContext before starting async load.

csharp
1public sealed partial class MainPage : Page
2{
3    public MainViewModel ViewModel { get; } = new MainViewModel();
4
5    public MainPage()
6    {
7        InitializeComponent();
8        DataContext = ViewModel;
9        _ = InitializeAsync();
10    }
11
12    private async Task InitializeAsync()
13    {
14        await ViewModel.LoadAsync(new ItemService());
15    }
16}

If DataContext is set after load starts, first binding pass may miss updates.

UI Thread Updates After Async Calls

In UWP, ObservableCollection updates should occur on UI thread. If service work runs on background threads, marshal updates using dispatcher.

csharp
1await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
2{
3    ViewModel.Items.Clear();
4    foreach (var item in data)
5        ViewModel.Items.Add(item);
6});

Cross-thread collection mutation can fail silently or throw depending on execution context.

Template and Styling Sanity Checks

Sometimes data binds correctly but template appears empty due to styling.

Quick checks:

  • text foreground color equals background color
  • parent style collapses content unintentionally
  • row height constraints clip inner elements

Temporarily simplify template to one visible TextBlock during debugging.

Debugging Sequence That Works

Use this order:

  1. confirm Items.Count after load
  2. inspect output window for binding errors
  3. verify DataContext and ItemsSource values at runtime
  4. confirm updates happen on UI thread
  5. simplify template to isolate visual layer issues

This sequence avoids guessing and pinpoints root cause fast.

Incremental Loading and Responsiveness

For large datasets, load a first page quickly and append more items incrementally. This prevents users from interpreting delayed render as template failure. Keep app responsive by batching UI updates instead of adding thousands of items in one dispatcher block.

Common Pitfalls

A common pitfall is replacing the ObservableCollection instance without raising property changed notification. Another is updating collection contents from background thread after await boundaries. Developers often bind to wrong property name after refactors. DataContext assignment timing is also frequently overlooked. Finally, binding error output is ignored, which delays root-cause discovery.

Summary

  • 'ObservableCollection is correct for live UWP list updates.'
  • Keep one stable collection instance and bind it once.
  • Assign DataContext before async loading begins.
  • Update collection on UI thread after async operations.
  • Use output binding diagnostics and minimal template tests.
  • Treat rendering issues as binding or threading problems first.

Course illustration
Course illustration

All Rights Reserved.