Are your .NET MAUI apps using lists to their full potential? Many developers overlook just how powerful and flexible list views can be—not just for displaying data, but for enabling rich, interactive experiences. In this post, we’ll walk step-by-step through everything you need to make your lists dynamic, beautiful, and user-friendly using .NET MAUI.
Understanding Lists in .NET MAUI
What is .NET MAUI?
.NET MAUI (Multi-platform App UI) is Microsoft’s evolution of Xamarin.Forms, designed for building native apps across iOS, Android, macOS, and Windows using C# and XAML. It unifies the app development experience, streamlining UI development across platforms with shared code.
The Role of Lists in Mobile/Desktop Apps
From to-do lists and product catalogs to user feedback panels and news feeds—lists are the bread and butter of application UIs. They present structured data cleanly and offer interaction points for users to engage with app content. A well-implemented list improves usability, data clarity, and performance.
Displaying Lists with CollectionView
Introducing CollectionView
CollectionView
is the go-to control for list rendering in .NET MAUI. It replaces the older ListView
with better performance, virtualization, and layout flexibility.
- Lightweight: Optimized for fast loading and low memory use.
- Flexible: Supports horizontal/vertical layouts and grid formatting.
- Customizable: Full control over templates and interactions.
Basic CollectionView Implementation
Here’s a simple example to display a list of strings:
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding}" FontSize="20" Padding="10" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
In the code-behind or ViewModel:
public ObservableCollection<string> Items { get; } = new()
{
"Apple",
"Banana",
"Orange"
};
This binds a simple list to a vertical scrollable list of text items.
Customizing Item Templates
Engage users with richer UIs using custom templates:
<DataTemplate>
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding ImageUrl}" WidthRequest="50" HeightRequest="50" />
<Label Grid.Column="1" Text="{Binding Name}" FontAttributes="Bold" FontSize="18" />
</Grid>
</DataTemplate>
This layout creates an avatar-style list entry.
Handling Empty States and Placeholders
Provide feedback when lists are empty or loading:
<CollectionView x:Name="MyCollectionView">
<CollectionView.EmptyView>
<Label Text="No data found." HorizontalOptions="Center" VerticalOptions="Center" />
</CollectionView.EmptyView>
</CollectionView>
You can also bind IsRefreshing
to show loading indicators.
Managing List Data Dynamically
Binding Data to CollectionView
Using ObservableCollection<T>
and MVVM, updates reflect automatically:
public ObservableCollection<Item> Items { get; } = new();
Changes like Items.Add(...)
or Items.Remove(...)
instantly update the UI.
Adding, Editing, and Deleting Items
Interactive CRUD (Create, Read, Update, Delete) operations:
Items.Add(new Item { Name = "Mango" });
Items[0].Name = "Grapes"; // UI will update automatically
Items.RemoveAt(1);
Use commands and bindings for user-triggered actions.
Refreshing and Sorting Lists
Enable pull-to-refresh with IsRefreshing
:
<RefreshView IsRefreshing="{Binding IsRefreshing}" Command="{Binding RefreshCommand}">
<CollectionView ItemsSource="{Binding Items}" />
</RefreshView>
Sorting is as simple as reordering the ObservableCollection
.
Paging and Lazy Loading
Efficiently manage large datasets:
- Use
RemainingItemsThreshold
andRemainingItemsThresholdReached
event. - Append more items as user scrolls.
collectionView.RemainingItemsThreshold = 5;
collectionView.RemainingItemsThresholdReached += (s, e) => LoadMoreItems();
Enhancing UX and Performance
Smooth Animations and Transitions
Make interactions feel polished and professional by using smooth animations. They help users understand state changes intuitively and enhance perceived performance.
await view.FadeTo(0, 250); // fade out
await view.FadeTo(1, 250); // fade in
For a better experience, combine with layout transitions or scale changes:
await view.ScaleTo(1.1, 100);
await view.ScaleTo(1, 100);
Use animations thoughtfully to highlight changes without overwhelming the user.
Best Practices for Performance
Optimizing list performance is essential for responsive apps:
- Use
CollectionView
overListView
for better memory and performance. - Apply
ItemSizingStrategy="MeasureFirstItem"
to reduce layout recalculations. - Keep item templates lightweight. Avoid unnecessary bindings or layout nesting.
- Use compiled bindings (
x:Bind
) where appropriate to reduce runtime overhead. - Load images asynchronously and cache them for smoother scrolling.
- Defer complex UI calculations (like dynamic height) until after render using
OnAppearing
or delayed tasks.
Accessibility and Responsiveness
Creating inclusive and adaptive interfaces is vital:
- Use
AutomationProperties.Name
andHelpText
to describe items for screen readers. - Adjust text sizes using
DynamicResource
for accessibility scaling. - Design UI layouts that adapt fluidly to orientation and screen size changes.
- Test using accessibility tools like Android’s TalkBack or iOS’s VoiceOver.
These practices ensure your apps are usable by everyone, regardless of ability or device.
Real-World Examples and Use Cases
To-Do List App
Create a simple task manager with add/edit/delete features. Bind a TaskItem
class to the list:
public class TaskItem
{
public string Title { get; set; }
public bool IsCompleted { get; set; }
}
<CollectionView ItemsSource="{Binding Tasks}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<CheckBox IsChecked="{Binding IsCompleted}" />
<Label Text="{Binding Title}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="Add Task" Command="{Binding AddTaskCommand}" />
Use ObservableCollection<TaskItem>
and commands to handle logic.
Product Catalog Viewer
Show a grid of products with images, prices, and lazy loading:
public class Product
{
public string Name { get; set; }
public string ImageUrl { get; set; }
public decimal Price { get; set; }
}
<CollectionView ItemsSource="{Binding Products}" ItemsLayout="VerticalGrid, 2">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame>
<StackLayout>
<Image Source="{Binding ImageUrl}" HeightRequest="100" />
<Label Text="{Binding Name}" />
<Label Text="{Binding Price, StringFormat='{}{0:C}'}" />
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Support filtering and pagination via bound commands.
User Feedback List
Collect feedback with a form and bind it to a live-updating list:
public class Feedback
{
public string UserName { get; set; }
public string Comment { get; set; }
}
<Entry Placeholder="Your name" Text="{Binding NewFeedback.UserName}" />
<Entry Placeholder="Your feedback" Text="{Binding NewFeedback.Comment}" />
<Button Text="Submit" Command="{Binding SubmitFeedbackCommand}" />
<CollectionView ItemsSource="{Binding FeedbackList}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding UserName}" FontAttributes="Bold" />
<Label Text="{Binding Comment}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Use ObservableCollection<Feedback>
and update the list in the SubmitFeedbackCommand
logic.
FAQ: Practical List Handling in .NET MAUI
Use ObservableCollection<T>
for auto UI updates.
Yes, use DataTemplateSelector
.
Optimize layout, use CollectionView
, and reduce image processing.
Use transitions like FadeTo
, TranslateTo
, or ScaleTo
.
Conclusion: Bring Lists to Life in .NET MAUI
A list isn’t just a container—it’s the heart of many applications. With the right approach in .NET MAUI, you can go beyond just displaying data to delivering delightful, interactive, and efficient list experiences. So go ahead, refactor that clunky old ListView and bring your UI to life!
Want more UI patterns and productivity tips? Drop a comment or explore other posts on the blog.