BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Data Display Controls - ListView

The one hundred and sixth part of the Windows Presentation Foundation Fundamentals tutorial returns to the topic of the WPF controls. This article looks at ListView, which is the first of the data display controls.

Data Display Controls

Now that we have seen the basic principles of data binding, it's time to return to the examination of the WPF controls. We'll now look at the data display controls. These are used to display large amounts of data in a list, grid or hierarchical tree structure. The first data display control that we'll consider is ListView.

ListView Control

The ListView control allows you to display a list of items from a collection. The display format is highly customisable, as you can specify a view that determines exactly how the items in the list should appear. This can be a standard view, provided by the .NET framework, or a custom view that you create yourself. In this article we'll use a standard view.

ListView inherits functionality from ListBox, which we saw in an earlier article. This means that you can use all of the features of a list box, such as the Items collection, the ItemsSource property for binding and the currently selected item properties. You can substitute a ListView for a ListBox to achieve the same results but with a richer user interface.

GridView

In this article we will use a ListView control with a view provided by the GridView class. GridViews arrange the items in the source collection into a list with multiple columns. Each column includes a header that the user can manipulate to resize or reorder the entire column. The data in the column is obtained using a data binding expression.

Let's demonstrate with a sample project. Create a new WPF application in Visual Studio named, "ListViewDemo". In the demo we'll use a list view to display the details of files, with columns for the file name, creation time and size in bytes. We'll hold these in a class called, "FileList".

Create a new class file called, "FileList" and ensure that the following three using directives are included, to simply access to the required namespaces.

using System.Collections.ObjectModel;
using System.IO;
using System.Windows;

The class will have several members that will control a window when a FileList object is set as its data context. The main property is a list of FileInfo objects in an observable collection, which will be bound to the ListView. We'll include a property for the path of the folder to interrogate and a method that refreshes the collection by reading the files from that path.

Update the class, as follows:

public class FileList
{
    public FileList()
    {
        Files = new ObservableCollection<FileInfo>();
    }

    public ObservableCollection<FileInfo> Files { get; private set; }

    public string Path { get; set; }

    public void RefreshFiles()
    {
        try
        {
            Files.Clear();
            foreach (FileInfo file in new DirectoryInfo(Path).GetFiles())
            {
                Files.Add(file);
            }
        }
        catch
        {
            MessageBox.Show("Unable to read folder", "Error",
                MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
}

Next, replace the XAML of the main window with the code below. This creates a ListView bound to the Files property, a TextBox for the path and a Button that we'll use to start the refresh process:

<Window x:Class="ListViewDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListView Demo"
        Height="300"
        Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="80"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <ListView Grid.ColumnSpan="3" ItemsSource="{Binding Files}"/>
        
        <TextBlock Grid.Row="1">Path</TextBlock>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path}" />
        <Button Grid.Row="1" Grid.Column="2">Refresh</Button>
    </Grid>
</Window>

At the moment, the ListView is not configured. We need to add the details of the view that we wish to use. In this case, we will be using a GridView, so add a GridView element to the ListView's View property, using property element syntax, as follows:

<ListView Grid.ColumnSpan="3" ItemsSource="{Binding Files}">
    <ListView.View>
        <GridView>
        </GridView>
    </ListView.View>
</ListView>

We can now add the column definitions using GridViewColumn objects. There are three key properties that we will set for each column. They are:

  • DisplayMemberBinding. This property determines the data that will be displayed in the column. You use a data binding expression to identify the information to retrieve from each item in the collection. In the case of the example code, the ListView is bound to the Files collection. When the binding expressions for the columns are processed, the data context for the binding expression will be one of the items from the collection, not the list itself. This means that you can reference properties from the items directly. For example, to show the FullName property in a column you could use the binding expression, "{Binding FullName}".
  • Header. This property sets the content of the header of the column. As you might expect with WPF, you can set the value to plain text or use other controls, including content controls with children, as the column header.
  • Width. Use this property to define the initial width for the column. If you supply a numeric value the width is measure in device-independent units. You can also use a qualified value that includes a measurement unit. The available units are the standard options of device-independent units (px), inches (in), centimetres (cm) or points (pt). You can also set the value to "Auto" to automatically size the column.

Update the GridView to add three columns:

<GridView>
    <GridViewColumn DisplayMemberBinding="{Binding FullName}" Header="Full Name" Width="200"/>
    <GridViewColumn DisplayMemberBinding="{Binding CreationTime}"
                    Header="Creation Time" Width="125"/>
    <GridViewColumn DisplayMemberBinding="{Binding Length}" Header="Size" Width="100"/>
</GridView>

Next, modify the constructor for the window to set the data context to a new FileList.

public MainWindow()
{
    InitializeComponent();
    DataContext = new FileList();
}

At this point you can run the program to see the window layout but you won't be able to populate the list. To enable this, we need to call the FileList's RefreshFiles method in response to clicking the button.

Update the XAML for the button to register the Click event:

<Button Grid.Row="1" Grid.Column="2" Click="Refresh_Click">Refresh</Button>

Next, add the code for the Click event:

private void Refresh_Click(object sender, RoutedEventArgs e)
{
    var dc = DataContext as FileList;
    dc.RefreshFiles();
}

Run the program to see the results. Initially the list view will be empty. Enter a valid path to a folder that contains files, then click the Refresh button. The list should be populated and appear similar to the image below:

WPF ListView

23 October 2014