List view and grid view

Most applications manipulate and display sets of data, such as a gallery of images or a set of email messages. The XAML UI framework provides ListView and GridView controls that make it easy to display and manipulate data in your app.

Important APIs: ListView class, GridView class, ItemsSource property, Items property

ListView and GridView both derive from the ListViewBase class, so they have the same functionality, but display data differently. In this article, when we talk about ListView, the info applies to both the ListView and GridView controls unless otherwise specified. We may refer to classes like ListView or ListViewItem, but the “List” prefix can be replaced with “Grid” for the corresponding grid equivalent (GridView or GridViewItem).

Is this the right control?

The ListView displays data stacked vertically in a single column. It's often used to show an ordered list of items, such as a list of emails or search results.

A list view with grouped data

The GridView presents a collection of items in rows and columns that can scroll vertically. Data is stacked horizontally until it fills the columns, then continues with the next row. It's often used when you need to show a rich visualization of each item that takes more space, such as a photo gallery.

Example of a content library

For a more detailed comparison and guidance on which control to use, see Lists.

Examples

XAML controls gallery

If you have the XAML Controls Gallery app installed, click here to open the app and see the ListView or GridView in action.

Create a list view

List view is an ItemsControl, so it can contain a collection of items of any type. It must have items in its Items collection before it can show anything on the screen. To populate the view, you can add items directly to the Items collection, or set the ItemsSource property to a data source.

Important  You can use either Items or ItemsSource to populate the list, but you can't use both at the same time. If you set the ItemsSource property and you add an item in XAML, the added item is ignored. If you set the ItemsSource property and you add an item to the Items collection in code, an exception is thrown.

Note  Many of the examples in this article populate the Items collection directly for the sake of simplicity. However, it's more common for the items in a list to come from a dynamic source, like a list of books from an online database. You use the ItemsSource property for this purpose.

Add items to the Items collection

You can add items to the Items collection using XAML or code. You typically add items this way if you have a small number of items that don't change and are easily defined in XAML, or if you generate the items in code at run time.

Here's a list view with items defined inline in XAML. When you define the items in XAML, they are automatically added to the Items collection.

XAML

<ListView x:Name="listView1"> 
   <x:String>Item 1</x:String> 
   <x:String>Item 2</x:String> 
   <x:String>Item 3</x:String> 
   <x:String>Item 4</x:String> 
   <x:String>Item 5</x:String> 
</ListView>  

Here's the list view created in code. The resulting list is the same as the one created previously in XAML.

C#

// Create a new ListView and add content. 
ListView listView1 = new ListView(); 
listView1.Items.Add("Item 1"); 
listView1.Items.Add("Item 2"); 
listView1.Items.Add("Item 3"); 
listView1.Items.Add("Item 4"); 
listView1.Items.Add("Item 5");

// Add the ListView to a parent container in the visual tree. 
stackPanel1.Children.Add(listView1); 

The ListView looks like this.

A simple list view

Set the items source

You typically use a list view to display data from a source such as a database or the Internet. To populate a list view from a data source, you set its ItemsSource property to a collection of data items.

Here, the list view's ItemsSource is set in code directly to an instance of a collection.

C#

// Instead of hard coded items, the data could be pulled 
// asynchronously from a database or the internet.
ObservableCollection<string> listItems = new ObservableCollection<string>();
listItems.Add("Item 1");
listItems.Add("Item 2");
listItems.Add("Item 3");
listItems.Add("Item 4");
listItems.Add("Item 5");

// Create a new list view, add content, 
ListView itemListView = new ListView();
itemListView.ItemsSource = listItems;

// Add the list view to a parent container in the visual tree.
stackPanel1.Children.Add(itemListView);

You can also bind the ItemsSource property to a collection in XAML. For more info about data binding, see Data binding overview.

Here, the ItemsSource is bound to a public property named Items that exposes the Page's private data collection.

XAML

<ListView x:Name="itemListView" ItemsSource="{x:Bind Items}"/>

C#

private ObservableCollection<string> _items = new ObservableCollection<string>();

public ObservableCollection<string> Items
{
    get { return this._items; }
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    // Instead of hard coded items, the data could be pulled 
    // asynchronously from a database or the internet.
    Items.Add("Item 1");
    Items.Add("Item 2");
    Items.Add("Item 3");
    Items.Add("Item 4");
    Items.Add("Item 5");
}

If you need to show grouped data in your list view, you must bind to a CollectionViewSource. The CollectionViewSource acts as a proxy for the collection class in XAML and enables grouping support. For more info, see CollectionViewSource.

Data template

An item’s data template defines how the data is visualized. By default, a data item is displayed in the list view as the string representation of the data object it's bound to. You can show the string representation of a particular property of the data item by setting the DisplayMemberPath to that property.

However, you typically want to show a more rich presentation of your data. To specify exactly how items in the list view are displayed, you create a DataTemplate. The XAML in the DataTemplate defines the layout and appearance of controls used to display an individual item. The controls in the layout can be bound to properties of a data object, or have static content defined inline. You assign the DataTemplate to the ItemTemplate property of the list control.

In this example, the data item is a simple string. You use a DataTemplate to add an image to the left of the string, and show the string in teal.

Note  When you use the x:Bind markup extension in a DataTemplate, you have to specify the DataType (x:DataType) on the DataTemplate.

XAML

<ListView x:Name="listView1">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="x:String">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="47"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Image Source="Assets/placeholder.png" Width="32" Height="32" 
                       HorizontalAlignment="Left"/>
                <TextBlock Text="{x:Bind}" Foreground="Teal" 
                           FontSize="15" Grid.Column="1"/>
            </Grid> 
        </DataTemplate>
    </ListView.ItemTemplate>
    <x:String>Item 1</x:String>
    <x:String>Item 2</x:String>
    <x:String>Item 3</x:String>
    <x:String>Item 4</x:String>
    <x:String>Item 5</x:String>
</ListView>

Here's what the data items look like when displayed with this data template.

List view items with a data template

Data templates are the primary way you define the look of your list view. They can also have a significant impact on performance if your list displays a large number of items. In this article, we use simple string data for most of the examples, and don't specify a data template. For more info and examples of how to use data templates and item containers to define the look of items in your list or grid, see Item containers and templates.

Change the layout of items

When you add items to a list view or grid view, the control automatically wraps each item in an item container and then lays out all of the item containers. How these item containers are laid out depends on the ItemsPanel of the control.

  • By default, ListView uses an ItemsStackPanel, which produces a vertical list, like this.

A simple list view

  • GridView uses an ItemsWrapGrid, which adds items horizontally, and wraps and scrolls vertically, like this.

A simple grid view

You can modify the layout of items by adjusting properties on the items panel, or you can replace the default panel with another panel.

Note  Be careful to not disable virtualization if you change the ItemsPanel. Both ItemsStackPanel and ItemsWrapGrid support virtualization, so these are safe to use. If you use any other panel, you might disable virtualization and slow the performance of the list view. For more info, see the list view articles under Performance.

This example shows how to make a ListView lay out its item containers in a horizontal list by changing the Orientation property of the ItemsStackPanel. Because the list view scrolls vertically by default, you also need to adjust some properties on the list view’s internal ScrollViewer to make it scroll horizontally.

Note  These examples are shown with the list view width unconstrained, so the horizontal scrollbars are not shown. If you run this code, you can set Width="180" on the ListView to make the scrollbars show.

XAML

<ListView Height="60" 
          ScrollViewer.HorizontalScrollMode="Enabled" 
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsStackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Item 1</x:String>
    <x:String>Item 2</x:String>
    <x:String>Item 3</x:String>
    <x:String>Item 4</x:String>
    <x:String>Item 5</x:String>
</ListView>

The resulting list looks like this.

A horizontal list view

In the next example, the ListView lays out items in a vertical wrapping list by using an ItemsWrapGrid instead of an ItemsStackPanel.

Note  The height of the list view must be constrained to force the control to wrap the containers.

XAML

<ListView Height="100"
          ScrollViewer.HorizontalScrollMode="Enabled" 
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Item 1</x:String>
    <x:String>Item 2</x:String>
    <x:String>Item 3</x:String>
    <x:String>Item 4</x:String>
    <x:String>Item 5</x:String>
</ListView>

The resulting list looks like this.

A list view with grid layout

If you show grouped data in your list view, the ItemsPanel determines how the item groups are layed out, not how the individual items are layed out. For example, if the horizontal ItemsStackPanel shown previously is used to show grouped data, the groups are arranged horizontally, but the items in each group are still stacked vertically, as shown here.

A grouped horizontal list view

Item selection and interaction

You can choose from various ways to let a user interact with a list view. By default, a user can select a single item. You can change the SelectionMode property to enable multi-selection or to disable selection. You can set the IsItemClickEnabled property so that a user clicks an item to invoke an action (like a button) instead of selecting the item.

Note  Both ListView and GridView use the ListViewSelectionMode enumeration for their SelectionMode properties. IsItemClickEnabled is False by default, so you need to set it only to enable click mode.

This table shows the ways a user can interact with a list view, and how you can respond to the interaction.

To enable this interaction: Use these settings: Handle this event: Use this property to get the selected item:
No interaction SelectionMode = None, IsItemClickEnabled = False N/A N/A
Single selection SelectionMode = Single, IsItemClickEnabled = False SelectionChanged SelectedItem, SelectedIndex
Multiple selection SelectionMode = Multiple, IsItemClickEnabled = False SelectionChanged SelectedItems
Extended selection SelectionMode = Extended, IsItemClickEnabled = False SelectionChanged SelectedItems
Click SelectionMode = None, IsItemClickEnabled = True ItemClick N/A

Note  Starting in Windows 10, you can enable IsItemClickEnabled to raise an ItemClick event while SelectionMode is also set to Single, Multiple, or Extended. If you do this, the ItemClick event is raised first, and then the SelectionChanged event is raised. In some cases, like if you navigate to another page in the ItemClick event handler, the SelectionChanged event is not raised and the item is not selected.

You can set these properties in XAML or in code, as shown here.

XAML

<ListView x:Name="myListView" SelectionMode="Multiple"/>

<GridView x:Name="myGridView" SelectionMode="None" IsItemClickEnabled="True"/> 

C#

myListView.SelectionMode = ListViewSelectionMode.Multiple; 

myGridView.SelectionMode = ListViewSelectionMode.None;
myGridView.IsItemClickEnabled = true;

Read-only

You can set the SelectionMode property to ListViewSelectionMode.None to disable item selection. This puts the control in read only mode, to be used for displaying data, but not for interacting with it. The control itself is not disabled, only item selection is disabled.

Single selection

This table describes the keyboard, mouse, and touch interactions when SelectionMode is Single.

Modifier key Interaction
None
  • A user can select a single item using the space bar, mouse click, or touch tap.
  • Ctrl
  • A user can deselect a single item using the space bar, mouse click, or touch tap.
  • Using the arrow keys, a user can move focus independently of selection.
  • When SelectionMode is Single, you can get the selected data item from the SelectedItem property. You can get the index in the collection of the selected item using the SelectedIndex property. If no item is selected, SelectedItem is null, and SelectedIndex is -1.

    If you try to set an item that is not in the Items collection as the SelectedItem, the operation is ignored and SelectedItem isnull. However, if you try to set the SelectedIndex to an index that's out of the range of the Items in the list, a System.ArgumentException exception occurs.

    Multiple selection

    This table describes the keyboard, mouse, and touch interactions when SelectionMode is Multiple.

    Modifier key Interaction
    None
  • A user can select multiple items using the space bar, mouse click, or touch tap to toggle selection on the focused item.
  • Using the arrow keys, a user can move focus independently of selection.
  • Shift
  • A user can select multiple contiguous items by clicking or tapping the first item in the selection and then the last item in the selection.
  • Using the arrow keys, a user can create a contiguous selection starting with the item selected when Shift is pressed.
  • Extended selection

    This table describes the keyboard, mouse, and touch interactions when SelectionMode is Extended.

    Modifier key Interaction
    None
  • The behavior is the same as Single selection.
  • Ctrl
  • A user can select multiple items using the space bar, mouse click, or touch tap to toggle selection on the focused item.
  • Using the arrow keys, a user can move focus independently of selection.
  • Shift
  • A user can select multiple contiguous items by clicking or tapping the first item in the selection and then the last item in the selection.
  • Using the arrow keys, a user can create a contiguous selection starting with the item selected when Shift is pressed.
  • When SelectionMode is Multiple or Extended, you can get the selected data items from the SelectedItems property.

    The SelectedIndex, SelectedItem, and SelectedItems properties are synchronized. For example, if you set SelectedIndex to -1, SelectedItem is set to null and SelectedItems is empty; if you set SelectedItem to null, SelectedIndex is set to -1 and SelectedItems is empty.

    In multi-select mode, SelectedItem contains the item that was selected first, and Selectedindex contains the index of the item that was selected first.

    Respond to selection changes

    To respond to selection changes in a list view, handle the SelectionChanged event. In the event handler code, you can get the list of selected items from the SelectionChangedEventArgs.AddedItems property. You can get any items that were deselected from the SelectionChangedEventArgs.RemovedItems property. The AddedItems and RemovedItems collections contain at most 1 item unless the user selects a range of items by holding down the Shift key.

    This example shows how to handle the SelectionChanged event and access the various items collections.

    XAML

    <StackPanel HorizontalAlignment="Right">
        <ListView x:Name="listView1" SelectionMode="Multiple" 
                  SelectionChanged="ListView1_SelectionChanged">
            <x:String>Item 1</x:String>
            <x:String>Item 2</x:String>
            <x:String>Item 3</x:String>
            <x:String>Item 4</x:String>
            <x:String>Item 5</x:String>
        </ListView>
        <TextBlock x:Name="selectedItem"/>
        <TextBlock x:Name="selectedIndex"/>
        <TextBlock x:Name="selectedItemCount"/>
        <TextBlock x:Name="addedItems"/>
        <TextBlock x:Name="removedItems"/>
    </StackPanel> 
    

    C#

    private void ListView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (listView1.SelectedItem != null)
        {
            selectedItem.Text = 
                "Selected item: " + listView1.SelectedItem.ToString();
        }
        else
        {
            selectedItem.Text = 
                "Selected item: null";
        }
        selectedIndex.Text = 
            "Selected index: " + listView1.SelectedIndex.ToString();
        selectedItemCount.Text = 
            "Items selected: " + listView1.SelectedItems.Count.ToString();
        addedItems.Text = 
            "Added: " + e.AddedItems.Count.ToString();
        removedItems.Text = 
            "Removed: " + e.RemovedItems.Count.ToString();
    }
    

    Click mode

    You can change a list view so that a user clicks items like buttons instead of selecting them. For example, this is useful when your app navigates to a new page when your user clicks an item in a list or grid. To enable this behavior:

    • Set SelectionMode to None.
    • Set IsItemClickEnabled to true.
    • Handle the ItemClick event to do something when your user clicks an item.

    Here's a list view with clickable items. The code in the ItemClick event handler navigates to a new page.

    XAML

    <ListView SelectionMode="None"
              IsItemClickEnabled="True" 
              ItemClick="ListView1_ItemClick">
        <x:String>Page 1</x:String>
        <x:String>Page 2</x:String>
        <x:String>Page 3</x:String>
        <x:String>Page 4</x:String>
        <x:String>Page 5</x:String>
    </ListView>
    

    C#

    private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
    {
        switch (e.ClickedItem.ToString())
        {
            case "Page 1":
                this.Frame.Navigate(typeof(Page1));
                break;
    
            case "Page 2":
                this.Frame.Navigate(typeof(Page2));
                break;
    
            case "Page 3":
                this.Frame.Navigate(typeof(Page3));
                break;
    
            case "Page 4":
                this.Frame.Navigate(typeof(Page4));
                break;
    
            case "Page 5":
                this.Frame.Navigate(typeof(Page5));
                break;
    
            default:
                break;
        }
    }
    

    Select a range of items programmatically

    Sometimes, you need to manipulate a list view’s item selection programmatically. For example, you might have a Select all button to let a user select all items in a list. In this case, it’s usually not very efficient to add and remove items from the SelectedItems collection one by one. Each item change causes a SelectionChanged event to occur, and when you work with the items directly instead of working with index values, the item is de-virtualized.

    The SelectAll, SelectRange, and DeselectRange methods provide a more efficient way to modify the selection than using the SelectedItems property. These methods select or deselect using ranges of item indexes. Items that are virtualized remain virtualized, because only the index is used. All items in the specified range are selected (or deselected), regardless of their original selection state. The SelectionChanged event occurs only once for each call to these methods.

    Important  You should call these methods only when the SelectionMode property is set to Multiple or Extended. If you call SelectRange when the SelectionMode is Single or None, an exception is thrown.

    When you select items using index ranges, use the SelectedRanges property to get all selected ranges in the list.

    If the ItemsSource implements IItemsRangeInfo, and you use these methods to modify the selection, the AddedItems and RemovedItems properties are not set in the SelectionChangedEventArgs. Setting these properties requires de-virtualizing the item object. Use the SelectedRanges property to get the items instead.

    You can select all items in a collection by calling the SelectAll method. However, there is no corresponding method to deselect all items. You can deselect all items by calling DeselectRange and passing an ItemIndexRange with a FirstIndex value of 0 and a Length value equal to the number of items in the collection.

    XAML

    <StackPanel Width="160">
        <Button Content="Select all" Click="SelectAllButton_Click"/>
        <Button Content="Deselect all" Click="DeselectAllButton_Click"/>
        <ListView x:Name="listView1" SelectionMode="Multiple">
            <x:String>Item 1</x:String>
            <x:String>Item 2</x:String>
            <x:String>Item 3</x:String>
            <x:String>Item 4</x:String>
            <x:String>Item 5</x:String>
        </ListView>
    </StackPanel>
    

    C#

    private void SelectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.SelectAll();
        }
    }
    
    private void DeselectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.DeselectRange(new ItemIndexRange(0, (uint)listView1.Items.Count));
        }
    }
    

    For info about how to change the look of selected items, see Item containers and templates.

    Drag and drop

    ListView and GridView controls support drag and drop of items within themselves, and between themselves and other ListView and GridView controls. For more info about implementing the drag and drop pattern, see Drag and drop.

    Get the sample code