# VBForums UtilityBank > UtilityBank - Tutorials >  WPF: Display items in a data grid format using ListView

## chris128

*How to create a DataGridView style ListView (like an editable ListView in Details mode in winforms terms)*
OK so this little mini tutorial isnt going to give you something that works _exactly_ the same as a DGV in windows forms but if you want that exact thing then you are just going to have to host the windows forms version within your WPF app arent you  :Smilie: 
Also I would like to point out that as I am fairly new to WPF still, there may be a better way of doing this... but this works for me so I figured it might help someone else out.


First things first, lets place a ListView onto our window, either by dragging and dropping it from the toolbox or by typing it in to the XAML code window.
Done that? Good! You should now have something like this in your XAML window:


```
<ListView Margin="14,68,13,26" Name="ListView1" />
```

Now because we are going to be placing things inside our ListView we need to open up the tag instead of having it close with a / at the end (by things I mean XAML code, not listview items). So change it to this:


```
<ListView Margin="14,68,13,26" Name="ListView1">

</ListView>
```

So now we have an area where we can type XAML tags in to and they will be 'inside' the listview so will affect just this one control.

OK, now that we have our ListView we need to make it look similar to how it looks in Winforms when you set the View style to Details. However, in WPF there is no such option so we should just give up and go home right? What do you mean your already at home!? . . . . Anyway! No we should not give up and go home, we should use the <ListView.View> tag to create a new view inside our ListView and then use the <GridView> tag to create a grid inside of that. Then inside of that tag, we can add <GridViewColumn> tags to create our columns!
Like so:


```
<ListView Margin="14,68,13,26" Name="ListView1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Test Column 1" />
                    <GridViewColumn Header="Test Column 2" />
                </GridView>
            </ListView.View>
</ListView>
```

As you can see we can use the Header attribute of the GridViewColumn to specify the text that will appear in the header of this column. Annoyingly you wont see these columns appear in the designer so you will have to run/debug your application to actually make sure they appear as they should.

We've got our data grid now, so whats next? Well, we need to load some data in to it dont we!

If your like me then you will probably be used to doing something like this in WinForms every single time you want to add/remove some items from a ListView:

vb.net Code:
Dim MyItem As New ListViewItem
MyItem.Text = "Stuff"
ListView1.Items.Add(MyItem)
but with WPF, there is no need to do that as we can bind pretty much anything to anything. What does that mean for this control? Well it means that we can bind the contents of our listview to a collection that we maintain in our code behind file (ie, in VB.NET code). Once this is setup then what this means is that if we want to add/remove/edit the items in our listview then we dont have to actually touch the listview at all. We can just edit our collection and the listview will instantly update itself.

This is the end of part 1 of this little tutorial, part 2 to follow in the next post very soon!

----------


## chris128

*Part 2 of how to use a ListView as a Data Grid in WPF*

Where were we? Oh yeah, we had a ListView on our form that contained columns that we were going to use, but we hadnt actually added any data to it yet.

So lets add some data!

Basically what we are going to do is create a collection (an _ObservableCollection_ to be precise) and then create a public property that exposes this collection so that we can bind our listview items to it. Note that it has to be a public property for the binding to work.

So I've made a little class here that will be used to create objects we want to add to our listview. Notice that I have made a public property for each value that I am going to be binding to one of the ListView columns.

vb.net Code:
Public Class Person
        Private _FirstName As String
        Private _Surname As String
         Public ReadOnly Property FirstName() As String
            Get
                Return _FirstName
            End Get
        End Property
         Public ReadOnly Property Surname() As String
            Get
                Return _Surname
            End Get
        End Property
         Public Sub New(ByVal FN As String, ByVal SN As String)
            _FirstName = FN
            _Surname = SN
        End Sub
End Class

Thats all well and good but we dont want to just bind our listview items to one instance of that structure, so we need to create a collection that will hold the list of these items. Again, I have created a public property to expose this collection so that we can bind to it:

vb.net Code:
'This is all at class level back in the form
Private _PersonCollection As New ObservableCollection(Of Person)
 Public ReadOnly Property PersonCollection() As ObservableCollection(Of Person)
        Get
            Return _PersonCollection
        End Get
End Property
So when our window is loaded a new instance of an ObservableCollection will be created and we have told our code that this collection will store objects of type "Person" as that is the name of our structure that will store our data.

For the sake of this example, lets just stick some code into our window_loaded event to populate this list:

vb.net Code:
_PersonCollection.Add(New Person("David", "Smith"))
_PersonCollection.Add(New Person("Joe", "Bloggs"))
 'Tell the listview to bind its item source to the public property
'that exposes the collection we created
ListView1.ItemsSource = PersonCollection

Now there are a couple of different ways you can do the last line in that code example. You can either do it in the XAML code or in your code behind at Window_Loaded. Personally I find it works better sticking it in the Loaded event, so thats what I have done.

The only thing left to do now is to tell our application which columns need to display which properties of each item in our collection. We can do this by using the DisplayMember attribute so lets go back to our XAML code and change the DataGridColumn tags to this:


```
<GridViewColumn Header="Test Column 1" DisplayMemberBinding="{Binding FirstName}"/>
<GridViewColumn Header="Test Column 2" DisplayMemberBinding="{Binding Surname}"/>
```

_Note that the properties you specify after the word Binding are case sensitive_


So there we have it. A grid like ListView that displays data from our collection, and of course now if we want to remove an item from that ListView we just remove it from the collection in the code-behind file and it automatically updates the ListView  :Smilie: 

Hope that helps someone out in the future and please feel free to post comments/suggestions.

----------


## chris128

*Part 3 - Applying DataTemplates to create editable TextBoxes for each item instead of read only text* 

Personally I usually have DataGridViews in ReadOnly mode in winforms and have a separate screen for editing them but I am sure some people use them in the way that lets users edit the data that is in them. So here is an example of how we can apply a DataTemplate to our items to allow the user to edit the data.

First thing we need to do is create the DataTemplate. I usually do this in my window resources tag right at the top of the XAML code, like so:


```
<Window.Resources>
        <DataTemplate x:Key="FirstNameItemTemplate">
            <TextBox Text="{Binding Path=FirstName,UpdateSourceTrigger=PropertyChanged}" />
         </DataTemplate>
</Window.Resources>
```

What we are doing here is creating a data template and all it does is create a textbox and bind its text property to the FirstName property. Also note that the UpdateSourceTrigger tells our app to update the binding source (our PersonCollection) as soon as a property is changed. This means that as soon as the text is changed the source gets updated, instead of the default setting which only updates the source when focus shifts away from the textbox. Obviously you can remove this if its not necessary in your situation.

So now we can set the First Name column to use this template by changing this line in our original XAML code:


```
<GridViewColumn Header="Test Column 1" DisplayMemberBinding="{Binding FirstName}"/>
```

to this:


```
<GridViewColumn Header="First Name" CellTemplate="{StaticResource FirstNameItemTemplate}"/>
```

We can do the same thing for the Surname column, create a data template for it:


```
<DataTemplate x:Key="SurnameItemTemplate">
            <TextBox Text="{Binding Path=Surname,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
```

and then apply it to the column:


```
<GridViewColumn Header="Surname" CellTemplate="{StaticResource SurnameItemTemplate}"/>
```

Now to make the text boxes stretch to fit our column width instead of being aligned to the left, we can add this style to our Window Resources:


```
<Style x:Key="StretchTextBoxStyle"  TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment"
                Value="Stretch" />
</Style>
```

and then apply it to the ListView by changing the ListView declaration to loo like this:


```
<ListView Margin="14,68,13,26" Name="ListView1" ItemContainerStyle="{StaticResource StretchTextBoxStyle}">
```

Notice that its the ItemContainerStyle that we are setting to our new style.

And there you go, you should now have an editable grid that updates a collection as it is edited  :Big Grin:

----------


## cyn3rgy

thanks so much for this post. I've spent a day trawling web sites and forums looking for a simple explanation of how to populate a multi-column listview. As I'm new to dot net (trying to update my skills from vbscript!) your post is just what I needed. The only thing I didn't realise was that I also needed to add 

```
Imports System.Collections.ObjectModel
```

 to my form and I got a bit confused where to sticl the _PersonCollection code but then realised it goes straight into my Page1.xaml.vb  code under the 

```
Class Page1
```

  Again thanks for the information and I hope my additions help someone who struggling.

cheers

Andrew

----------


## chris128

Glad it helped  :Smilie:  and thanks for the comments, im sure they will help someone out

----------


## cyn3rgy

Hi Chris

Do you have any clues on making this type of listview sortable by clicking on the column headings? I've found this example on msdn http://msdn.microsoft.com/en-us/library/ms745786.aspx but it's in C# and I have no idea how to convert it to vb. Wondering if you've come up against this before?

cheers

Andrew

----------


## chris128

I havent tried that but converting C# to VB is very easy, there are even free online converters that do a half decent job of it for you. This one for example: http://www.developerfusion.com/tools.../csharp-to-vb/

----------


## abhijit

How would you go about binding an image? 
If I have an image in my database (blob column) that has the employee's photograph, how do I go about displaying it on the GridView? Will bind work in that case?

----------


## abhijit

This is what I have tried:

xml Code:
in my XAML Code
                <GridView>
                    <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}"/>
                    <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding Surname}"/>
                    <GridViewColumn Header="Date Of Birth" DisplayMemberBinding="{Binding DateOfBirth}"/>
                    <GridViewColumn Header="Photo" DisplayMemberBinding="{Binding IdPic}"/>
                </GridView>
            </ListView.View>
        </ListView>
        <Image Height="34" HorizontalAlignment="Left" Margin="33,269,0,0" Name="imgPic" Stretch="Fill" VerticalAlignment="Top" Width="42" Source="/DataBrowser;component/Images/smoking_av.jpg" />

All I am trying to do is get the image displayed in the grid control. 
The next step is to fetch this from a database and then populate the grid.

----------

