Dela via


Quickstart: adding ListView and GridView controls (XAML)

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

You can use a ListView or GridView control in XAML to display your data collections, such as a list of contacts, images in a gallery, or the contents of an email inbox.

Objective: To learn how to add ListView and GridView controls to a Windows Store app.

Prerequisites

We assume that you can add controls to a basic Windows Runtime app using C++, C#, or Visual Basic. For instructions on adding a control, see Quickstart: Adding controls and handling events.

Instructions

1. Choosing a ListView or GridView

The ListView and GridView controls are both used to display collections of data in your app. They have similar functionality, but display data differently. They are both derived from the ItemsControl class. When we talk about an ItemsControl, the info applies to both the ListView and GridView controls.

The ListView displays data stacked vertically. It's often used to show an ordered list of items, such as a list of emails or search results. It's also useful in master-detail scenarios, where the list items contain only a small amount of info and the details of the selected item are shown separately.

The GridView displays data stacked horizontally. It's often used when you need to show a rich visualization of each item that takes more space, such as a photo gallery.

You can populate an ItemsControl by adding items directly to its Items collection, or by binding its ItemsSource property to a data source. It's common to have both a ListView and GridView bound to the same data source. You can then show one and hide the other to adapt your UI to different orientations and resolutions.

Here's a ListView showing items in an app that is narrow when next to another app, and a GridView showing the same items when the app is full screen.

2. Adding items to the Items collection

You can add items to the Items collection using Extensible Application Markup Language (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 ListView with items defined inline using XAML, and a GridView with items added in code.

<ListView x:Name="listView1" SelectionChanged="ListView_SelectionChanged">
    <x:String>Item 1</x:String>
    <x:String>Item 2</x:String>
</ListView>
// Create a new grid view, add content, 
// and add a SelectionChanged event handler.
GridView^ gridView1 = ref new GridView();
gridView1->Items->Append("Item 1");
gridView1->Items->Append("Item 2");
gridView1->SelectionChanged += 
    ref new SelectionChangedEventHandler(this, &MainPage::GridView_SelectionChanged);

// Add the grid view to a parent container in the visual tree.
stackPanel1->Children->Append(gridView1);
// Create a new grid view, add content, 
// and add a SelectionChanged event handler.
GridView gridView1 = new GridView();
gridView1.Items.Add("Item 1");
gridView1.Items.Add("Item 2");
gridView1.SelectionChanged += GridView_SelectionChanged;

// Add the grid view to a parent container in the visual tree.
stackPanel1.Children.Add(gridView1);
' Create a new grid view, add content, 
' and add a SelectionChanged event handler.
Dim gridView1 = New GridView()
gridView1.Items.Add("Item 1")
gridView1.Items.Add("Item 2")
AddHandler gridView1.SelectionChanged, AddressOf Me.GridView_SelectionChanged

' Add the grid view to a parent container in the visual tree.
stackPanel1.Children.Add(gridView1)

When you add items to an ItemsControl they are automatically placed in an item container. The item container for a ListView is ListViewItem, and the item container for a GridView is GridViewItem. To change how an item is displayed you can apply a style to the item container by setting the ItemContainerStyle property.

When you define the items in XAML, they are automatically added to the Items collection.

3. Setting the items source

Most apps use a ListView or GridView to display data from a source such as a database or the Internet. To populate an ItemsControl from a data source, you set its ItemsSource property to a collection of data items.

Note  You can populate an ItemsControl either by adding items to its Items collection, or by setting its ItemsSource property, but you can't use both ways 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.

 

Here are some common collection types that support binding to an ItemsControl.

Collection type When to use
List(Of T) When the collection doesn't change at runtime. The content of the list or grid is static after it's created.
ObservableCollection(Of T) When the collection can change at runtime. The list or grid is notified of changes to the collection and updates the display.
FileInformationFactory.GetVirtualizedFilesVector Bind to a collection of files.
FileInformationFactory.GetVirtualizedFoldersVector Bind to a collection of folders.
FileInformationFactory.GetVirtualizedItemsVector Bind to a collection of storage items.

 

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

// Data source.
Platform::Collections::Vector<String^>^ itemsList = 
    ref new Platform::Collections::Vector<String^>();
itemsList->Append("Item 1");
itemsList->Append("Item 2");

// Create a new grid view, add content, 
// and add a SelectionChanged event handler.
GridView^ gridView1 = ref new GridView();
gridView1->ItemsSource = itemsList;
gridView1->SelectionChanged += 
    ref new SelectionChangedEventHandler(this, &MainPage::GridView_SelectionChanged);

// Add the grid view to a parent container in the visual tree.
stackPanel1->Children->Append(gridView1);
// Data source.
List<String> itemsList = new List<string>();
itemsList.Add("Item 1");
itemsList.Add("Item 2");

// Create a new grid view, add content, 
// and add a SelectionChanged event handler.
GridView gridView1 = new GridView();
gridView1.ItemsSource = itemsList;
gridView1.SelectionChanged += GridView_SelectionChanged;

// Add the grid view to a parent container in the visual tree.
stackPanel1.Children.Add(gridView1);
' Data source.
Dim itemsList = New List(Of String)()
itemsList.Add("Item 1")
itemsList.Add("Item 2")

' Create a new grid view, add content, 
' and add a SelectionChanged event handler.
Dim gridView1 = New GridView()
gridView1.ItemsSource = itemsList
AddHandler gridView1.SelectionChanged, AddressOf Me.GridView_SelectionChanged

' Add the grid view to a parent container in the visual tree.
stackPanel1.Children.Add(gridView1)

You can also bind the ItemsSource property to a CollectionViewSource. The CollectionViewSource acts as a proxy for the collection class to enable currency and grouping support. If you have the same data bound to both a ListView and GridView to support switching between narrow and wide views, you should bind to a CollectionViewSource so that both views have the same current item. For more info, see Data binding with XAML.

To show grouped items in a list or grid, the data source must support grouping, and you must bind the ItemsSource to a CollectionViewSource with it's IsSourceGrouped property set to True. For more info, see How to group items in a data control.

Here, the ItemsSource is bound to a CollectionViewSource named itemsViewSource. To see complete code for this and the later examples, create an app using the Split Application template in Microsoft Visual Studio.

<Page.Resources>
    <!-- Collection of items displayed by this page -->
    <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Items}"/>
</Page.Resources>
<ListView x:Name="itemListView" 
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"/>

4. Specifying the look of the items

By default, a data item is displayed in the list or grid 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.

You typically want to display more than one property of your data item. To specify exactly how items in the list or grid are displayed, you create a DataTemplate. The XAML in the DataTemplate defines the layout of controls used to display an individual item. The controls in the layout can be bound to properties of a data object, or have content defined inline. The DataTemplate is assigned to the ItemTemplate property of the ListView or GridView.

In this example, the ItemTemplate of a ListView is defined inline. Examples in later sections show how to bind the ItemTemplate to a named static resource.

<ListView x:Name="itemListView"
          Margin="120,0,0,60"
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
          SelectionChanged="ItemListView_SelectionChanged">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
                    <Image Source="{Binding Image}" Stretch="UniformToFill"/>
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>          
</ListView>

Here's what the layout defined by the data template looks like.

5. Specifying the layout of the view

To specify how the items are laid out in a list or grid view, you set the ItemsPanel property to specify an ItemsPanelTemplate that is set to a layout Panel. By default, GridView uses a WrapGrid panel as its ItemsPanel, and ListView uses a VirtualizingStackPanel as its ItemsPanel.

Here's how to use a WrapGrid to change the layout of items in a ListView. The WrapGrid replaces the default VirtualizingStackPanel, which arranges items in a single column. We set the WrapGrid.MaximumRowsOrColumns property so that items are arranged in 2 columns.

<ListView Height="320" Width="260">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="2"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>

    <Rectangle Height="100" Width="100" Fill="Blue" />
    <Rectangle Height="100" Width="100" Fill="Red" />
    <Rectangle Height="100" Width="100" Fill="Yellow" />
    <Rectangle Height="100" Width="100" Fill="Green" />
    <Rectangle Height="100" Width="100" Fill="Gray" />
    <Rectangle Height="100" Width="100" Fill="LightBlue" />
    <Rectangle Height="100" Width="100" Fill="Pink" />
    <Rectangle Height="100" Width="100" Fill="YellowGreen" />
</ListView>

Here's what the ListView looks like using a WrapGrid with 2 columns as its ItemsPanel.

6. Adding a header to the view

You can add a header to a ListView or GridView by assigning a string or object to the Header property. You can use a data template to define the layout of the Header by setting the HeaderTemplate property.

By default, the header is shown on the leading edge of the view. It's shown at the top for a ListView, and on the left for a GridView. If the FlowDirection property is set to RightToLeft, the header is shown on the right for a GridView.

Here's a GridView with a header that contains a StackPanel with text and an image. This XAML is a simplified version of the GridView used in GroupDetail page of the Visual Studio Grid App template.

<GridView x:Name="itemGridView"
          Margin="0,-14,0,0"
          Padding="120,0,120,50"
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
          ItemTemplate="{StaticResource Standard500x130ItemTemplate}">

    <GridView.Header>
        <StackPanel Width="480" Margin="0,4,14,0">
            <TextBlock Text="{Binding Subtitle}" Margin="0,0,18,20" 
                       Style="{StaticResource SubheaderTextStyle}" MaxHeight="60"/>
            <Image Source="{Binding Image}" Height="400" Margin="0,0,18,20" 
                   Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
            <TextBlock Text="{Binding Description}" Margin="0,0,18,0" 
                       Style="{StaticResource BodyTextStyle}"/>
        </StackPanel>
    </GridView.Header>
</GridView>

Here, the header of the GridView is the part outlined in yellow.

7. Setting the interaction mode of the view

By default, a user can select a single item in a ListView or GridView. To change this behavior, you can set the SelectionMode property to a ListViewSelectionMode enumeration value to allow multi-selection or to disable selection.

Here's a ListView with selection disabled, and a GridView with multi-selection enabled.

<ListView x:Name="itemList"
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
          SelectionMode="None"/>

<GridView x:Name="itemGrid"
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
          SelectionChanged="ItemView_SelectionChanged"
          SelectionMode="Extended"/>

To respond to selection changes in a list or grid, handle the SelectionChanged event. In the event handler code, you can get the list of selected items from the SelectionChangedEventArgs.AddedItems property. Outside of the SelectionChanged event, you get the selected items from the SelectedItem and SelectedItems properties, either in code or through data binding.

Here's the SelectionChanged event handler for GridView in the previous example.

List<object> selectedItems;

private void ItemView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Use e.AddedItems to get the items that are selected in the ItemsControl.
    selectedItems = (List<object>)e.AddedItems;
}

You can also change a ListView or GridView 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 the SelectionMode to None, set IsItemClickEnabled to true, and handle the ItemClick event to do something when your user clicks and item.

Here's a GridView with clickable items. The code in the ItemClick handler navigates to a new page and passes the clicked item as the data for the new page.

<GridView x:Name="itemGridView"
          Margin="116,0,116,46"
          ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
          ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
          SelectionMode="None"
          IsItemClickEnabled="True"
          ItemClick="ItemView_ItemClick"/>
private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
    // Navigate to the split page, configuring the new page
    // by passing required information as a navigation parameter
    this.Frame.Navigate(typeof(SplitPage), e.ClickedItem);
}

Summary and next steps

You learned how to create ListView and GridView controls to display collections of data.

For a list of predefined item templates you can use in your app, see Item templates for list layouts and Item templates for grid layouts. To learn how to group items, see How to group items in a list or grid.

For more code examples that show the ListView and GridView controls, see these samples:

Roadmap for Windows Runtime apps using C# or Visual Basic

Roadmap for Windows Runtime apps using C++