Results 1 to 9 of 9

Thread: WPF: Display items in a data grid format using ListView

  1. #1

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    WPF: Display items in a data grid format using ListView

    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
    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:
    Code:
    <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:
    Code:
    <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:
    Code:
    <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:
    1. Dim MyItem As New ListViewItem
    2. MyItem.Text = "Stuff"
    3. 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!
    Last edited by chris128; May 27th, 2009 at 07:39 AM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  2. #2

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: WPF'isms: Things that can cause frustration please read

    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:
    1. Public Class Person
    2.         Private _FirstName As String
    3.         Private _Surname As String
    4.  
    5.         Public ReadOnly Property FirstName() As String
    6.             Get
    7.                 Return _FirstName
    8.             End Get
    9.         End Property
    10.  
    11.         Public ReadOnly Property Surname() As String
    12.             Get
    13.                 Return _Surname
    14.             End Get
    15.         End Property
    16.  
    17.         Public Sub New(ByVal FN As String, ByVal SN As String)
    18.             _FirstName = FN
    19.             _Surname = SN
    20.         End Sub
    21. 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:
    1. 'This is all at class level back in the form
    2. Private _PersonCollection As New ObservableCollection(Of Person)
    3.  
    4. Public ReadOnly Property PersonCollection() As ObservableCollection(Of Person)
    5.         Get
    6.             Return _PersonCollection
    7.         End Get
    8. 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:
    1. _PersonCollection.Add(New Person("David", "Smith"))
    2. _PersonCollection.Add(New Person("Joe", "Bloggs"))
    3.  
    4. 'Tell the listview to bind its item source to the public property
    5. 'that exposes the collection we created
    6. 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:
    Code:
    <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

    Hope that helps someone out in the future and please feel free to post comments/suggestions.
    Last edited by chris128; May 27th, 2009 at 07:42 AM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  3. #3

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: WPF: Display items in a data grid format using ListView

    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:
    Code:
    <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:
    Code:
    <GridViewColumn Header="Test Column 1" DisplayMemberBinding="{Binding FirstName}"/>
    to this:
    Code:
    <GridViewColumn Header="First Name" CellTemplate="{StaticResource FirstNameItemTemplate}"/>
    We can do the same thing for the Surname column, create a data template for it:
    Code:
    <DataTemplate x:Key="SurnameItemTemplate">
                <TextBox Text="{Binding Path=Surname,UpdateSourceTrigger=PropertyChanged}" />
    </DataTemplate>
    and then apply it to the column:
    Code:
    <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:
    Code:
    <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:
    Code:
    <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
    Last edited by chris128; Jan 26th, 2009 at 07:35 PM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  4. #4
    New Member
    Join Date
    Jun 2009
    Posts
    2

    Thumbs up Re: WPF: Display items in a data grid format using ListView

    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
    Code:
    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
    Code:
    Class Page1
    Again thanks for the information and I hope my additions help someone who struggling.

    cheers

    Andrew

  5. #5

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: WPF: Display items in a data grid format using ListView

    Glad it helped and thanks for the comments, im sure they will help someone out
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  6. #6
    New Member
    Join Date
    Jun 2009
    Posts
    2

    Re: WPF: Display items in a data grid format using ListView

    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

  7. #7

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: WPF: Display items in a data grid format using ListView

    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/
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  8. #8
    PowerPoster abhijit's Avatar
    Join Date
    Jun 1999
    Location
    Chit Chat Forum.
    Posts
    3,226

    Re: WPF: Display items in a data grid format using ListView

    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?
    Everything that has a computer in will fail. Everything in your life, from a watch to a car to, you know, a radio, to an iPhone, it will fail if it has a computer in it. They should kill the people who made those things.- 'Woz'
    save a blobFileStreamDataTable To Text Filemy blog

  9. #9
    PowerPoster abhijit's Avatar
    Join Date
    Jun 1999
    Location
    Chit Chat Forum.
    Posts
    3,226

    Red face Re: WPF: Display items in a data grid format using ListView

    This is what I have tried:
    xml Code:
    1. in my XAML Code
    2.                 <GridView>
    3.                     <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}"/>
    4.                     <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding Surname}"/>
    5.                     <GridViewColumn Header="Date Of Birth" DisplayMemberBinding="{Binding DateOfBirth}"/>
    6.                     <GridViewColumn Header="Photo" DisplayMemberBinding="{Binding IdPic}"/>
    7.                 </GridView>
    8.             </ListView.View>
    9.         </ListView>
    10.         <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.
    Everything that has a computer in will fail. Everything in your life, from a watch to a car to, you know, a radio, to an iPhone, it will fail if it has a computer in it. They should kill the people who made those things.- 'Woz'
    save a blobFileStreamDataTable To Text Filemy blog

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width