WPF Tutorial - Using The ListView, Part 1

Skill

WPF Tutorial - Using The ListView, Part 1

Posted in:

Many of the controls in WPF have a downright dizzying array of capabilities and features, due in large part to the composibility of all the components. The ListView control is a great example of this - the possibilities are almost endless. This series of tutorials on the ListView will hopefully make the space of possible options seem not quite as daunting.

We will be starting today with a simple grid based list view, showing how to create columns and some different ways of getting data into those columns. This tutorial won't be very exciting - we will mostly just be setting up the basics for use in some of the later parts. Hopefully, the series will culminate in a sort of "DataGridView" for WPF (a control that, sadly, does not yet exist in WPF). I say hopefully cause I haven't yet written the code for those parts :P

Ok, so here's a screenshot of a ListView with a few columns and no data. Nothing really fancy, but the basic starting point.

Empty ListView

The code to create this is just as boring:

<Window x:Class="ListViewTest.Test0.ListViewTest"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="Empty ListView Grid" Height="216" Width="435">
 <ListView>
  <ListView.View>
   <GridView>
    <GridViewColumn Width="140" Header="Column 1" />
    <GridViewColumn Width="140" Header="Column 2" />
    <GridViewColumn Width="140" Header="Column 3" />
   </GridView>
  </ListView.View>
 </ListView>
</Window>

The special code here is in the ListView.View section. This is what changes the list view from your standard wrapping list of items into something else - in this case a GridView. Don't confuse the GridView with the standard WPF Grid control - they are very different. Pretty much the only thing that is the same is that they both have the word Grid in the name.

So we make a GridView and then we make a couple GridViewColumns. These GridViewColumns have a lot more functionality than is used here - we will start to see that in the later examples and especially in later tutorials. There are a couple nice things that you automatically get with the GridView and GridViewColumns - first off, the columns can be resized by the user exactly like, say, the columns in Windows Explorer. Also, the user can drag+drop to reorder columns, and you don't have to worry about it at all. One thing that is missing, though, is some built in sorting capability - but it isn't that hard to add on (we will be doing that in a later tutorial).

Ok, enough about that. Lets throw some data into this grid!

Listview with dates

And heres the xaml code:

<Window x:Class="ListViewTest.Test1.ListViewTest"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:sys="clr-namespace:System;assembly=mscorlib"
   Title="Some Dates" Height="216" Width="435">  
  <ListView>
    <ListView.View>
      <GridView>
        <GridViewColumn Width="120" Header="Date" />
        <GridViewColumn Width="120" Header="Day Of Week"  
           DisplayMemberBinding="{Binding DayOfWeek}" />
        <GridViewColumn Width="120" Header="Year"
           DisplayMemberBinding="{Binding Year}" />
      </GridView>
    </ListView.View>
    <sys:DateTime>1/2/3</sys:DateTime>
    <sys:DateTime>4/5/6</sys:DateTime>
    <sys:DateTime>7/8/9</sys:DateTime>
    <sys:DateTime>10/11/12</sys:DateTime>
  </ListView>
</Window>

So there are a couple changes to the xaml here. First, I imported the System namespace and registered it to "sys", because I wanted to use some DateTime objects as my ListView data. Next, you can see that two of the GridViewColumns have a DisplayMemberBinding property now. And finally, there are the 4 dates which are the data for the ListView.

The only part that probably needs explaining is the DisplayMemberBinding property. This property tells the column what data from an entry should be displayed in that column. As you can see, the first column does not have this property set, so it just does a toString on the date object for each row to determine what to put in that column. The second column is bound to the DayOfWeek property on the DateTime object - and so in that column the day of the week for each of those dates is printed. And for the third column, we have bound to the Year property, and so we get the year out. Pretty cool, eh?

Now you're probably thinking thats all well and good, but you want to display your own data objects, and you want to be able to add and remove them on the fly. No worries there - the ListView has got you covered!

Listview with games

Here we make a departure for using just XAML - there is actually (gasp!) some C# code behind. So lets take a look:

<Window x:Class="ListViewTest.Test2.ListViewTest"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   DataContext="{Binding RelativeSource={RelativeSource Self}}"
   Title="Some Game Data" Height="216" Width="435">
  <StackPanel>
    <ListView ItemsSource="{Binding GameCollection}">
      <ListView.View>
        <GridView>
          <GridViewColumn Width="140" Header="Game Name"
             DisplayMemberBinding="{Binding GameName}"  />
          <GridViewColumn Width="140" Header="Creator"  
             DisplayMemberBinding="{Binding Creator}" />
          <GridViewColumn Width="140" Header="Publisher"
             DisplayMemberBinding="{Binding Publisher}" />
        </GridView>
      </ListView.View>
    </ListView>
    <Button HorizontalAlignment="Right" Margin="5,5,5,5"
       Content="Add Row" Click="AddRow_Click" />
  </StackPanel>
</Window>

And the code behind:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace ListViewTest.Test2
{
  public partial class ListViewTest : Window
  {
    ObservableCollection<GameData> _GameCollection =
        new ObservableCollection<GameData>();

    public ListViewTest()
    {
      _GameCollection.Add(new GameData {
          GameName = "World Of Warcraft",
          Creator = "Blizzard",
          Publisher = "Blizzard" });
      _GameCollection.Add(new GameData {
          GameName = "Halo",
          Creator = "Bungie",
          Publisher = "Microsoft" });
      _GameCollection.Add(new GameData {
          GameName = "Gears Of War",
          Creator = "Epic",
          Publisher = "Microsoft" });

      InitializeComponent();
    }

    public ObservableCollection<GameData> GameCollection
    { get { return _GameCollection; } }

    private void AddRow_Click(object sender, RoutedEventArgs e)
    {
      _GameCollection.Add(new GameData {
          GameName = "A New Game",
          Creator = "A New Creator",
          Publisher = "A New Publisher" });
    }
  }

  public class GameData
  {
    public string GameName { get; set; }
    public string Creator { get; set; }
    public string Publisher { get; set; }
  }
}

So what we have here is a set of GameData objects that we want to display in the ListView. The GameData objects have a Game Name, a Creator, and a Publisher, and so we create three columns in the ListView and bind them each to the appropriate fields. One thing to note - and I'll probably elaborate on this more if I ever get around to a tutorial on WPF Binding - you can only bind to public properties/methods/dependency properties. You can't bind to private things, or to fields. The syntax I used in the GameData class right above is syntactic sugar for not having to write out the full property definition. When the code is compiled, those lines for GameName, etc., turn into properties with a backing private field.

So we have some GameData objects - how do we get them into the ListView? Well, we create an ObservableCollection of them. ObservableCollection is not your normal everyday generic list - it can tell other pieces of code when the contents of the collection change. You'll see why this comes in handy in a moment.

Now that we have this collection (and we have created a public field for it) what do we do with it? Well, we bind it as the ItemsSource of the ListView. This is where the fact that the collection is observable comes in handy - now the ListView gets alerted whenever anything changes inside of the collection, and can update accordingly. For example, when you press the "Add Row" button, a new GameData instance is added to the collection. The ListView is notified, and so is able to update and display the new row.

Ok, well that is it for this first tutorial on the WPF ListView. You can get the source code for all three examples here if you would like it. Stay tuned for future tutorials on the ListView, covering topics like sorting, filtering, and how to configure the look of the cells in the view. As always, feel free to leave any questions or comments.

Calciu Sorin
05/10/2008 - 09:56

Hi.
This is great. I have learned a lot of things from this post.
I have one more question.
How to bind data when you have an undetermined number of columns at design time. From example bind from an string[] at runtime, and create as many columns as needed.
Thanks.

reply

zenonB
03/07/2009 - 20:16

to do that, you access the GridView component of your ListView:
var grid = YourListView.View as GridView;
grid.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding("String1") });
grid.Columns.Add(new GridViewColumn() { DisplayMemberBinding = new Binding("String2") });
etc.

reply

Marouan
06/09/2008 - 12:06

Hi,
Thank you very much, this was very usefull for me, like all the others posts.
Greate job.

reply

Carlos Misael
07/09/2008 - 17:08

excelente

reply

Ray Akkanson
07/23/2008 - 07:34

Great article.

Ray Akkanson

reply

Steve
07/28/2008 - 13:46

Interesting and useful article. I think it would be worthwhile to call a little more attention to the addition of the "DataContext="{Binding RelativeSource={RelativeSource Self}}"" line in the Window definition in the XAML though.

Took me a while to figure out that this was what was preventing the databinding in my application from working . . .

reply

Anonymous
06/12/2009 - 12:46

That is a HUGE and good point Steve. Beat my head against a wall for three weeks on this problem (along with some others) and I want to thank you for pointing that out.

Thanks

reply

Ketan
11/04/2009 - 16:40

Yeah thanks from me too.

I was trying to figure this for ages.

reply

Charith
08/06/2008 - 22:52

Hi,

Thanks for the great article. I want to know how to make listview data editable?? (Editable Cells).

As I have seen with several other forums, we can celltemplate for this and we can add text boxes to each and every cell. But this is quite complex, do you have any other simple solution for making editable ?

Thanks!

reply

Vikas Thukral
10/02/2008 - 01:10

hI, cAN ANYONE PLZ TELL ME HOW CAN I SET WIDTH OF COLUMN DYANAMICALLY EQUAL TO SIZE OF DATA COMING IN COLUMN

THANKS
IN ADVANCE

reply

The Reddest
10/02/2008 - 10:23

According to the MSDN article on column width, the column defaults to that behavior. You can also explicitly set the Width to "Auto".

The only downside is that this only works for currently visible rows since the ListView is virtualized. Meaning when the collection is bound, the only rows that will affect the column's width will be those that are currently visible - so if you have a longer item that is not scrolled into view, it will be cut off. You can probably get around it by changing the ItemsPanel, but it's not something I've tried on a ListView.

reply

A Person
10/21/2008 - 10:22

This article is horrible. The author set forth to create a simple ListView tutorial- Great! However the author added complexity on top of the simplicity that makes it hard for the intended audience to understand. Worse episode ever! You reader calling it great suck too.

reply

The Reddest
10/21/2008 - 10:53

A Person, unfortunately the ListView in WPF is inherently difficult to use by requiring binding. This article is about as simple as it gets for creating and populating one.

I like hearing different views about articles, however I think this article and our readers are great!

reply

WTF
11/02/2009 - 12:31

Pretty simple and well explained. If you didn't get it, then you are in the wrong business

reply

Ron
02/12/2010 - 02:59

I'm new to WPF myself. This article is QUITE good. Please don't be insulting the good people who do their best to spread the knowledge, and do it well.

To the author, my gratitude.

reply

prolingua.geo
02/18/2010 - 11:21

Hi A Person,
I don't agree with you. I think the article is good.
I think you'd better ask the author or other audience any parts you don't understand. That's much better than moaning.

reply

Chris M
03/05/2010 - 14:31

A Person,
I can't disagree with you more. This article was extremely useful in explaining a rather difficult concept, for beginners. The only part he missed as Steve pointed out was not drawing more attention to the DataContext.

Great job by the author on this, it was super helpful.

reply

Yuyu
10/26/2008 - 05:12

Many thanks! Short, clear, useful. Great!

reply

Faduhur
11/01/2008 - 00:08

Gud tutorial!!! for a beginner....

can u please explain me how to delete a selected row from the grid......

reply

Christopher
11/09/2008 - 21:22

Hi! Very usefull artice, like 4 me :)

Thanks!

reply

Michelkeijzers
11/19/2008 - 08:56

I have noticed that it works ok when adding/deleting items to an ObservableCollection. However, when editing an item (via a separate dialog), the listview is not repopulated automatically or should I call some change notification?

reply

Vinoth
12/11/2008 - 23:44

hi can anyone say how to show some animation when user just move the mouse pointer over the list items in listview using wpf & c#.for example. i ve 3 items in the listview, when i move over th first item,then that list item should show some animation letting to know to the user that he/she ve move over that correspoding listitem.

reply

Vinoth
12/11/2008 - 23:47

expecting a great help from the .net lovers to solve this problem, as this is my first and foremost requirement in my assignment, kindly make it as fast as possible please,
thanks to all in advance and the article abov is of vey great for the users, thanks to the author

reply

brownhead
01/25/2009 - 20:49

Excellently written and not precisely what I was looking for but very related and saved me a large amount of time. Thanks yet again for teaching me something I didn't know. I love this site.

reply

Manjeet
04/09/2009 - 05:26

Excellently written and Very Good.
Thanks

reply

Abid
06/10/2009 - 11:17

Can anyone tel me how can we turn on the gridlines, i mean both the horizontal and vertical.

reply

The Reddest
06/10/2009 - 11:26

Unfortunately, I don't think there's an easy way to do that. Here's a solution I've used in the past.

http://www.designerwpf.com/2007/12/11/how-do-i-set-up-grid-lines-for-my-listview/

reply

MIkeA
07/16/2009 - 11:58

Hi There
Thanks, it was a very good article. My question is, how to get data from SQL server.

Thanks
MikeA

reply

BruceL
10/01/2009 - 09:58

Excellent example, both clear and simple! Spent a vary frustraiting day trying to find this solution online before I ran across yours.

I still don't understand why:

 
public class GameData
{
   public string GameName;
   public string Creator;
   public string Publisher;
}

doesn't work but figure I'll run across the answer eventually. (It doesn't crash but the DisplayMemeberBinding can't find them so you get a blank ListView.)

Thanks So Much!
Bruce

reply

The Reddest
10/01/2009 - 11:43

It doesn't work because those fields aren't properties, they're just public member variables. To make it work change those fields to properties:

public class GameData
{
  public string GameName { get; set; }
  public string Creator { get; set; }
  public string Publisher { get; set; }
}

reply

Arthur
02/09/2010 - 14:37

One addition: make sure that the list is a propery too. Else it will not work.

reply

grkowalski
11/26/2009 - 03:35

This was a great article. I struggled during the day to get my ListView to populate from a collection, and a quick search brought me here and you had the answer. Thank you.

reply

Mohammad
12/27/2009 - 12:00

Thanks , it was very useful.

reply

AKB
03/04/2010 - 21:28

This was very informative and easy to understand. Thanks.

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.

Sponsors