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 :
OK, so here's a screenshot of a ListView with a few columns and no data.
Nothing really fancy, but the basic starting point.
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!
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!
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.
Source Files:
Comments
Post a Comment