Skip to main content

List View – Skinning and Data Binding with Expression Blend 3

Author: Vibor Cipan, Microsoft User Experience Evangelist
Blog: http://www.uxpassion.com/

Expression Newsletter, subscribe now to get yours.

List View is one of the most powerful controls available in WPF, offering you a number of capabilities for working with and presenting the data. In this article I am going to show you how you can play with the look of the ListView control. I will first change its appearance using the Expression Blend 3, and then I will show you how to use data-binding to connect to an external data source such as an XML file. I will also make couple of changes just to show you how simple it is to make some significant changes using the Blend and hopefully to inspire you to go and try experiments on your own.

You can download the sample ListView control created in this article from the Expression Gallery at:   http://gallery.expression.microsoft.com/en-us/SkinningWPFList

One of the great things regarding WPF in general is the fact that the way controls look is separated from how the control behaves. In other words, we are able to completely change the appearance of the control and while maintaining all functionality and behavior. That is also great from a developer—designer collaboration perspective, where developers can write the code and functionality without interfering with designers who are changing the overall control’s appearance.

So, let’s start.

Getting Started

The first thing you will need is Expression Blend 3. You can get the free trial from the Expression product site.

Once you’ve installed Expression Blend 3, start a new WPF project. From the Asset Library, draw a List View control on top of the LayoutRoot. Don’t bother with the positioning and size; we will not be really focusing on that part of design right now.

Binding the XML data to ListView

Today, most of the user interfaces for typical LOB (line of business) applications are being driven by data in one way or another. Controls might use data from external XML files, databases, or other data sources. In this example I will show you how easy it is to bind the ListView control to an external XML file.

You can find a sample XML file called emps.xml within the XMLData folder in solution.

The XML file is pretty simple—it contains information about employees in one company in this form:

<?xml version="1.0" encoding="utf-8" ?>
<Employees>
  <Employee>
    <EmpId>1</EmpId>
    <Name>Vibor</Name>
    <LastName>Cipan</LastName>
    <Sex>Male</Sex>
    <City>Copenhagen</City>
    <Country>Denmark</Country>
  </Employee>
</Employees>

My goal is to get these data into our ListView so that it can be easily viewed and organized.

With Expression Blend 3 there have been some changes to the process of data binding; the whole process is now more “what-you-see-is-what-you-get.”. I will combine pure data-binding through Blend UI and some XAML code writing just to encourage you to get your hands dirty in XAML, because sometimes this approach can be very rewarding in terms of productivity gains—and, besides that, it is interesting to see how we can combine both approaches and decide which one to use when developing and designing our real-life applications.

Add Sample Data

The first step is to add the sample data source to our project. Click the Data pane and then click the Add sample data source icon. From the drop-down menu, click Import Sample Data from XML…

A dialog box will appear. Browse for your XML file containing the data you need. Also, make sure that you check the option asking you to enable sample data during application testing. When you are done, click OK.

Now you should see a structural representation of your data under the Data pane in Expression Blend 3.

You can edit your XML data by clicking the Edit sample values icon (next to the EmployeeCollection label). I will skip this step in this tutorial for now, but at the end of this tutorial I will explain how to generate some sample data.

You will also notice that Blend has generated a DataSource called empsSampleDataSource1 for us. This is the DataSource we are going to use and bind to.

Bind the Sample Data to the Control

Now, right-click your ListView control (you can either right-click it on your artboard, or you can right-click its name under the Objects and Timeline pane). From the drop-down menu, select Bind ItemsSource to Data. The Create Data Binding dialog box will appear.

Be sure that you are on the Data Field tab. Under Data Sources you should be able to see our data source—empsSampleDataSource1. Select it, and then under the Fields list, select Employees to expand the node and see EmployeeCollection and its children elements. Select EmployeeCollection (Array) and click OK.

If you now take a look at the ListView control, you will notice that it is populated with one really long string but not with real data from our XML file.

Define GridView

To achieve that, we need to define a GridView for our ListView control. GridView is one possible view for the ListView control, enabling us to see data in grid-like representation.

You can define a new GridView without writing any XAML code. Select your ListView control and, under the Properties pane, locate the Common Properties section. Click New to the right of the View (GridView) label. Then click the “…” button to the right of the Columns (Collection). That will enable you to create columns for your GridView.

After you click the button, a new GridViewColumn Collection Editor: Columns dialog box will appear. Click the “Add another item” button and a new item called [0] GridViewColumn will appear under the Items list on the left side of the dialog. Click it and, on the right side, you will see a number of properties you can change.

Locate the Header property and type “ID”. What you type in your Header property, it will become a caption-header for first column.

Now click OK and examine the XAML code. It should like this:

<ListView Margin="0,0,0,0" IsSynchronizedWithCurrentItem="True" Style="{DynamicResource ListViewStyle1}" ItemsSource="{Binding Path=EmployeeCollection, Mode=Default}">
  <ListView.View>
    <GridView>
      <GridViewColumn Header="ID"/>
    </GridView>
  </ListView.View>
</ListView>

Now edit the GridViewColumn element and to look like this:

<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Path=EmpId}"/>

Press F5 to test your application. You will notice that first column is populated with data from the XML file.

Now you can just copy and paste that GridColumnView line to make changes in the XAML code that create columns for all data in your XML file. It should look like this:

<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Path=EmpId}"/>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding Path=Name}"/>
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding Path=LastName}"/>
<GridViewColumn Header="Sex" DisplayMemberBinding="{Binding Path=Sex}"/>
<GridViewColumn Header="City" DisplayMemberBinding="{Binding Path=City}"/>
<GridViewColumn Header="Country / State" DisplayMemberBinding="{Binding Path=Country}"/>

An important thing to notice here is the DisplayMemberBinding property, which tells us to which XML element a specific column should be bound. Those elements are designated as a Path and are the same as in XML file (since we are using XPath logic).

What if you need some more sample data?

In this example we’ve used data from an XML file. What if you want to test your application with larger amounts of data and you don’t really feel like typing lines and lines of data?

Expression Blend 3 gives you a great feature enabling you to generate sample data. All you need to do is to click the “Edit sample values” icon (the one near the EmployeeCollection under the Data pane) and a new dialog box will appear. It will contain data you have entered previously that has been imported from XML file.

Now just enter, let’s say, “50” for Number of records, and Blend will automatically generate sample data for you. Click F5 to start your application and enjoy.

Changing the ScrollBar appearance

Now that we’ve added some XML and auto-generated data to our control, let’s change the default look of the ListView vertical scroll bar. Without any modifications, the regular ListView populated with some generic items looks like this:

What we’d like to do now is to change the look of the vertical scrollbar. In its current appearance you need to click the buttons at the end of the scrollbar to scroll the content up or down. I will show you how to position those buttons one above other, pretty much like it is on Mac OS applications. If you are not familiar with scrollbar layout on Mac OS systems, they have buttons located close to each other, like this:

Let’s do it now in Blend.

In the Objects and Timeline pane, right-click the ListView control. From the drop-down menu, select Edit Control Parts (Template) > Edit a Copy. The Create Style Resource dialog box will appear. You can leave all settings as they are and just click OK.

Notice that your scope has now reduced, and that under the Objects and Timeline pane, you don’t see your complete visual tree—what you see is a template structure of your ListView control. As you can see, it is composed of a Border control called Bd, a ScrollViewer, and ItemsPresenter.

Since we want to change look of our scrollbar, we will need to dig deeper into ScrollViewer. We will follow the same procedure for creating a copy and editing a template for ListView. So, right-click ScrollViewer and again, from the drop-down menu, select Edit Control Parts (Template) > Edit Template.

Now the structure gets a bit more complex. Let’s see what we have here:

Expand all nodes to see the structure. Luckily, we don’t need to get deeper into all of them, but since we are interested in changing the vertical scroll bar, we need to dig a bit deeper. As you might guess already, we need to edit a copy of PART_VerticalScrollBar’s template. So, once again, right click PART_VerticalScrollBar, and then select Edit Control Parts (Template) > Edit a Copy.

The Create Style Resource dialog box appears. Accept the defaults and then press Enter or click OK.

Now the structure changes once again—but all you need to know at this moment is that everything is being contained within the Grid control (called Bg) and that we have two RepeatButton parts as well as a PART_Track which is composed of an IncreaseRepeatButton, a Thumb, and a DecreaseRepeatButton.

We will focus on the top-level RepeatButton parts, since they are the ones matching buttons we would like to modify. The picture below shows both RepeatButton parts selected and their visual appearance.

At this point I assume that you are familiar with the basics of the Grid control, and that you know that we can split a Grid control into rows and columns and position other containers and controls into them.

Let’s take a closer look at our Bg Grid control and its contents.

Select Bg under the Objects and Timelines pane and you will see a blue outline. As you can see, the Bg Grid control is divided into three rows. Press F11 to open XAML (Code) view. Press F11 again to enter Split view, which allows you to see both the design and code. Let’s see the Bg structure in XAML code.

<Grid x:Name="Bg" SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
  <Grid.RowDefinitions>
    <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
    <RowDefinition Height="0.00001*"/>
    <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
  </Grid.RowDefinitions>
    <...>
</Grid>

I’ve trimmed the some code to make this significant part more readable. We can see three row definitions corresponding to the previous picture.

If you now select the first RepeatButton, and under the Properties pane look for the Layout section, you will see its Row property with value “0”. Now select PART_Track and see that Row changes to “1”; if you select the last RepeatButton, Row will be “2”. These values are telling us which row the specific control or part is occupying. So, to position the first RepeatButton right above the last one, we need to change its Row from “0” to “1” and then change PART_Track to Row “0”.

But we are not done; we need to make changes to our RowDefinitions as well.

We can do that directly in XAML:

<Grid x:Name="Bg" SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
  <Grid.RowDefinitions>
    <RowDefinition Height="0.00001*"/>
    <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
    <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
  </Grid.RowDefinitions>
    <...>
</Grid>

So I’ve just switched positions for the first and second RowDefinitions.

Manually changing the XAML is nice, but it can be messy and lead to more errors. To be less error prone and more flexible, we can rely on Blend’s support and use the Row Definition CollectionEditor to change row order for our Grid. To do that, select the Bg gird and, under the Properties pane, locate Layout section. Click the down arrow to show advanced options. Find the RowDefinitions (Collection) button and select it. The Row Definition CollectionEditor will appear.

On the left side you can see all available Items (Row Definitions), and on the right side you have access to the properties of the selected item. So, instead of changing those values directly in XAML code, you can set them here; and when it comes to changing the RowDefinition position, you can just select the desired item and move it up or down using the arrows located in the bottom-left corner of the Collection Editor.

Press F5 to start your application. It should look like this:

As you can see, the RepeatButton parts are now positioned one above other and they are fully functional. And, as expected, all the data we have created (both from XML file and from auto-generating) is visible.

Of course, possibilities for further customizations are immense Experiment with editing different templates to create even more interesting and usable designs, both for ListView and for other controls as well.