I wrote an article recently explaining how to create a Gridview that exports selected rows to Excel, and have received a number of queries about how to do the same with a Listview.  The Listview, like the Gridview, doesn't automatically remember whether a checkbox is selected or not for each row, unless you store the value immediately in a database after each change, which is inefficient.

This example shows how to maintain checkbox state across paging and sorting within a Listview.  The final steps in Gridview that exports selected rows to Excel will show you how to export these rows to Excel if you wish.

 Maintaining Checkbox State in a Listview

 

Demo | Code

Step 1 - Create a Listview

The ListView control was introduced in ASP.NET 3.5.  It is an enhancement to the DataList and Repeater controls, and works by using templates to determine how records are formatted.  This gives you the flexibility to display mulitple records in a horizontal or vertical grid, or in groups of 3 etc.  For this example. the Listview I create will mimic the data display of a Gridview.

The basic layout of the Listview control is as follows:

<asp:ListView ID="ListView" runat="server">
    <LayoutTemplate>
        ...
    </LayoutTemplate>
    <ItemTemplate>
        ...
    </ItemTemplate>
</asp:ListView>

I am using a simple table of four data columns, with a fifth column that will display the checkboxes.  I have also included a DataPager control which handles the Listview's paging.

<asp:ListView ID="Listview1" runat="server" DataKeyNames="ID" DataSourceID="dsListView">
    <LayoutTemplate>
        <table cellpadding="0" cellspacing="0" class="ListviewTable" width="540">
            <tr>
                <th style="width: 120px">
                    Fist Name
                </th>
                <th style="width: 120px">
                    Last Name
                </th>
                <th style="width: 120px">
                    Department
                </th>
                <th style="width: 120px">
                    Location
                </th>
                <th style="width: 60px; text-align: center">
                </th>
            </tr>
            <tr id="itemPlaceholder" runat="server" />
            <tr>
                <td colspan="5" align="center">
                    Page:
                    <asp:DataPager ID="DataPager1" runat="server" PageSize="12">
                        <Fields>
                            <asp:NumericPagerField ButtonCount="5" />
                        </Fields>
                    </asp:DataPager>
                </td>
            </tr>
        </table>
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td>
                <%#Eval("FirstName") %>
            </td>
            <td>
                <%#Eval("LastName") %>
            </td>
            <td>
                <%#Eval("Department") %>
            </td>
            <td>
                <%#Eval("Location") %>
            </td>
            <td style="text-align: center">
                <asp:CheckBox ID="chkSelect" runat="server" AutoPostBack="true" />
            </td>
        </tr>
    </ItemTemplate>
</asp:ListView>

 

Step 2: Create a list variable that will store ID's of selected rows

In your code behind file, create a Private Property that will store the ID's of your selected rows:

Private ReadOnly Property IDs() As List(Of Integer)
    ' Create a list of ID's that are selected.  ID's is the primary
    ' Key for this table
    Get
        If Me.ViewState("IDs") Is Nothing Then
            Me.ViewState("IDs") = New List(Of Integer)()
        End If
        Return CType(Me.ViewState("IDs"), List(Of Integer))
    End Get
End Property

 

Step 3: Create a Sub that will store the selected row ID's into your list variable

Now we create a Sub that I called AddRowstoIDList which goes through all the currently visible rows and adds the ones that have a checkbox selected to the private list variable created in step 2.

Protected Sub AddRowstoIDList()
    ' Loop through all the current items in the Listview
    For Each lvi As ListViewDataItem In ListView1.Items
        ' Find the checkbox in each row
        Dim chkSelect As CheckBox = CType(lvi.FindControl("chkSelect"), CheckBox)
        ' If the checkbox is ticked then add the corresponding ID to our private list
        If (Not (chkSelect) Is Nothing) Then
            ' Get the ID from the datakeynames property
                Dim ID As Integer = 
            Convert.ToInt32(Listview1.DataKeys(lvi.DisplayIndex).Value)
            If (chkSelect.Checked AndAlso Not Me.IDs.Contains(ID)) Then
                ' Add the ID to our list
                Me.IDs.Add(ID)
            ElseIf (Not chkSelect.Checked AndAlso Me.IDs.Contains(ID)) Then
                ' Not checked - remove the ID from our list
                Me.IDs.Remove(ID)
            End If
        End If
    Next
End Sub
 
This sub is then called whenever the Listview is paged or sorted - we want to get the current status of the items and update our list before the Listview refreshes:
 
Protected Sub ListView1_PagePropertiesChanging(ByVal sender As Object, 
        ByVal e As System.Web.UI.WebControls.PagePropertiesChangingEventArgs) 
        Handles Listview1.PagePropertiesChanging
    AddRowstoIDList()
End Sub

Protected Sub ListView1_Sorting(ByVal sender As Object, 
        ByVal e As System.Web.UI.WebControls.ListViewSortEventArgs) 
        Handles Listview1.Sorting
    AddRowstoIDList()
End Sub

 

Step 4: Make sure the checkboxes are displayed correctly when the Listview is refreshed

The next step is to set the status of each checkbox correctly when the Listview is refreshed, by a sort of paging operation for example.  We do this by checking each item, finding the checkbox control, and checking it if the row ID exists in our list.

Protected Sub ListView1_ItemDataBound(ByVal sender As Object, 
        ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
        Handles Listview1.ItemDataBound
    ' Get each Listview Item on DataBound
    Dim lvi As ListViewDataItem = e.Item
    If (lvi.ItemType = ListViewItemType.DataItem) Then
        ' Find the checkbox in the current row
        Dim chkSelect As CheckBox = CType(lvi.FindControl("chkSelect"), CheckBox)
        ' Make sure we're referencing the correct control
        If (Not (chkSelect) Is Nothing) Then
            ' If the ID exists in our list then check the checkbox
            Dim ID As Integer = Convert.ToInt32(ListView1.DataKeys(lvi.DisplayIndex).Value)
            chkSelect.Checked = Me.IDs.Contains(ID)
        End If
    End If
End Sub

 

That's it!  The code is very similar to the last article about the Gridview, but there are some gotcha's, particularly in how to reference items within the Gridview.

Check out the Demo or download the source code.

Bartek Marnane

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Comments

Comments are closed