(Data) Bound & Determined

Working with the ListView Control in ASP.NET 3.5

LANGUAGES: VB.NET

ASP.NET VERSIONS: 3.5

ASP.NET 3.5 introduces a new data-bound control: the ListView control. The ListView control was created to add to the capabilities of other data-bound controls, such as the Repeater and the DataList controls, and to give you complete control over the HTML markup generated.

The ListView control is a templated data-bound control. This means that ListView requires user-defined templates for its rendering. ListView supports automatic insert, edit, delete, and sort operations, provided its bound data source object supports these capabilities. And the ListView control also supports paging functionality by using another new control in ASP.NET 3.5, the DataPager control. The ListView control provides several templates to control its rendering (see Figure 1).

Template

Description

LayoutTemplate

This is the main container of the control. It can contain group or item placeholders.

ItemTemplate

This template identifies the layout for each item.

ItemSeparatorTemplate

Use when you want to define content to be rendered between each item.

GroupTemplate

Use when you want to group items. You also need to set the GroupItemCount property.

GroupSeparatorTemplate

Use when you want to define content to be rendered between each group of items.

EmptyItemTemplate

If you are using the GroupTemplate, you can use this template to define the layout for empty items.

EmptyDataTemplate

This template identifies content to be rendered when no data is returned from the data source.

SelectedItemTemplate

Use when you want to differentiate the selected item from the other displayed items.

AlternatingItemTemplate

Use when you want to distinguish consecutive items.

EditItemTemplate

Use when you want to add edit functionality. This defines the layout for the item in edit mode.

InsertItemTemplate

Use when you want to add insert functionality. You also need to set the InsertItemPosition property.

Figure 1: The available templates in the ListView control.

 

Creating a Basic Layout

To use the ListView control, you must always define at least two templates: LayoutTemplate and ItemTemplate.

LayoutTemplate is where you define the root container for your UI. A root container typically contains one or more HTML container elements, such as a div, table, or ul element. Somewhere inside LayoutTemplate you add a placeholder object with its ID set to itemPlaceholder and with the runat= server attribute. (By default, you must use the ID itemPlaceholder, although it s possible to specify a different ID as the reserved identifier for an item placeholder by setting the ItemPlaceholderID property.) This placeholder object will be replaced at run time with the actual content defined for the item. Also, if you want to edit templates using the designer, you must make sure the container controls of the item placeholder object have an ID, as well. A point that might be potentially confusing is that the placeholder element can be anything you like. As noted, it s replaced in its entirety at run time, so it essentially doesn t matter what element you use, as long as it has the correct ID and the runat= server attribute. (To avoid confusion and to ensure the designer will work, it is recommended you use the same element for the placeholder that you will use for the item template.)

Define the layout of each item inside ItemTemplate. This will contain controls that use a binding expression (the Eval function) to retrieve and display values from the data source. Figure 2 shows the markup for a basic ListView layout using a SqlDataSource object.

 

Photos


  • Figure 2: A basic ListView layout.

     

    If you compare the ListView control to the Repeater control, you ll notice that the ListView control doesn t contain header and footer templates, because the LayoutTemplate will contain the main structure as a whole. The markup shown in Figure 2 generates a photo list where each item renders an image with a caption. The output produced by this markup is shown in Figure 3.

     


    Figure 3: Output generated by the code in Figure 2.

     

    Because the ListView control doesn t support style properties, you need to style the control inside the templates by using CSS classes or inline style. But this gives you great control over the layout, and you can easily hook up existing style sheet files to use with the ListView control. Note that the markup shown in Figure 2 uses inline style to customize the rendering for the div, ul, and li elements.

    The ListView control also provides some pre-defined layouts and styles that you can use after you set the data source object. To use that, open the Design view, then go to the smart tag menu of the control and select Configure ListView.

     

    Adding Sort, Select, Update, Delete, and Insert Capabilities

    The ListView control supports some operations automatically, provided its bound data source object also supports them. If the data source does not support the behavior you want, you can implement it by handling a ListView control event.

    You need to add buttons to perform update, delete, insert, select, and sort operations automatically, and they need to be placed in the appropriate template. (This is similar to how you work with the other templated data-bound controls.) The ListView control recognizes the operation requested based on the CommandName property of the button. Figure 4 shows the list of recognized values and their function.

     

    Value

    Function

    Cancel

    Cancels an edit or insert operation. Used in the InsertItemTemplate or EditItemTemplate templates.

    Delete

    Deletes the item from the data source.

    Edit

    Puts the item in edit mode and renders the EditItemTemplate for the item.

    Insert

    Inserts the bound values into the data source. Used in the InsertItemTemplate.

    Select

    Selects the item and renders the SelectedItemTemplate for the selected record.

    Sort

    Sorts the columns listed in the CommandArgument property of the button.

    Update

    Updates records in the data source. Used in the EditItemTemplate.

    Figure 4: A list of the recognized CommandName property values.

    You can also provide a custom value for the CommandName property. In this case, there is no action as a default behavior. But you can create an event-handling method for the ItemCommand event and add functionality there for your custom action.

     

    Sorting and Selecting an Item

    Figure 5 shows the markup for a ListView control that shows data from a table that contains two columns: LastName and FirstName. In LayoutTemplate, a header row was added and each header cell is a LinkButton control that enables users to sort by the corresponding field. The buttons CommandName property is set to Sort, so the ListView control performs sorting and you don t have to write any code to handle this task. This markup also shows how to select an item by adding a button to the ItemTemplate. Using the same technique, the button s CommandName property is set to Select to select the item.

     

    
    
     
    
      
     
    <%#Eval("LastName")%> <%#Eval("FirstName")%> &nsbp; <%#Eval("LastName")%> <%#Eval("FirstName")%>

    Figure 5: A ListView control with sort and select functionality.

     

    Inserting, Updating, and Deleting

    To enable insert, update, and delete operations in the ListView control, you must set the primary keys of the table in the DataKeyNames property. (If you use the Configure Data Source smart-tag command on the designer to set up data binding, this might be done automatically for you.) For the insert or edit operations only, you must also define the InsertItemTemplate and EditItemTemplate templates. The controls inside the templates can be created using two-way binding expressions with the Bind function (for controls that will be used to modify or create values). This way, the values are automatically passed to the data source object. For the insert operation, you also need to set the InsertItemPosition property of the ListView control to a value different than None so the template can be displayed. If you set the property to FirstItem, the ListView control renders the insert template before all data items; if you set it to LastItem, the control renders the insert template in the end of the page.

    Figure 6 shows an example of a ListView control that uses the same database table as Figure 5, but the control has the update, insert, and delete operations enabled. Four templates are defined in the markup: LayoutTemplate, ItemTemplate, EditItemTemplate, and InsertItemTemplate. The insert template is displayed at the bottom of the ListView control because the InsertItemPosition is set to LastItem.

     

    
    
     
    
       

    Figure 6: A ListView control that has insert, edit, and delete operations.

     

    It is important to notice that the tr element from InsertItemTemplate and EditItemTemplate doesn t contain the runat= server attribute. This will break the design-time experience; however, it is necessary when you are using tr or td elements as placeholders for the templates that use two-way data binding expressions at run time. If you leave the runat attribute, it can result in data loss at run time. The markup shown in Figure 6 generates a table where each row shows a record. The output produced by this markup is shown in Figure 7.


    Figure 7: Output generated by the code in Figure 6.

     

    Adding Paging Functionality

    The ListView control doesn t have a built-in paging feature, but you can easily add paging functionality by adding a DataPager control to your page or inside the LayoutTemplate of the ListView control. It provides paging for any control that implements the IPageableItemContainer interface. So far, the only control that implements this interface is the ListView control.

    The DataPager control lets you use a combination of pre-defined pager fields. It provides the NextPreviousPagerField object that contains First/Next/Previous/Last buttons (which you can selectively remove) and the NumericPagerField object that enables you to navigate using the page numbers. The DataPager control also has the TemplatePagerField field type that enables you to create a customized UI. By setting the PageSize property in the DataPager control, you determine the number of records that are displayed per page.

    Figure 8 shows an example of a ListView control that uses an XmlDataSource control that reads the entries from an RSS feed, and contains a DataPager control inside the LayoutTemplate to add paging functionality. This example also adds an AlternatingItemTemplate to the ListView control to distinguish one row from another.

     

    
    
     
    
       

    <%#Convert.ToDateTime(XPath("pubDate")).ToShortDateString()%> <%#Convert.ToDateTime(XPath("pubDate")).ToShortDateString()%>
    Figure 8: A ListView control that has paging functionality.

    Using the markup shown in Figure 8 lets you create a pager that shows a First Page button, the page numbers, and a Last Page button. If you place the DataPager control outside the ListView control, you also need to set the PagedControlID property so the pager knows what data to page.

     

    Creating Groups of Items

    The ListView control includes the GroupTemplate template which you won t find in the other data controls. The GroupTemplate enables you to repeat a certain content for a specified number of items. In other words, this template enables you to display items in groups table rows, individual div elements, or whatever other grouping you want. Specify how many items are in each group, then create a layout not only for the items, but for the group as a whole.

    The number of items displayed for each group is defined by the GroupItemCount property. The most common application of this template is when you want to create a tiled table layout.

    For grouping the items, add a group placeholder object to the LayoutTemplate instead of an item placeholder. To do this, add a placeholder object with its ID set to groupPlaceholder and with the runat= server attribute. This placeholder object will be replaced at run time with the actual content defined for the group.

    Then, inside the GroupTemplate, define the grouping layout and your item placeholder object. Add the item placeholder object with its ID set to itemPlaceholder and with the runat= server attribute. This placeholder object will be replaced at run time with the actual content defined for the item.

    When you group items, it is useful to define content for another template, the EmptyItemItemplate. This template will be rendered when there are no more items to display in a page.

    Figure 9 shows an example of a ListView control using the grouping feature. This ListView control is using a new data source object in ASP.NET 3.5, the LinqDataSource control. A LINQ to SQL data model was created for the Employees table to be able to use the LinqDataSource control.

     

    
    
     
    
       
    Employees
     

    Figure 9: A ListView control with a tiled table layout that is created by grouping.

     

    As you can see in the markup shown in Figure 9, both ID values used for the placeholder objects (itemPlaceholder and groupPlaceholder) can be changed by using the ItemPlaceholderID and GroupPlaceholderID properties. Again, if you want to edit templates using the designer, you must ensure the container controls of the placeholder objects have an ID, as well.

    The markup shown in Figure 9 generates a table with two records per row. The last row has an empty item, because in the example data set, there is an odd number of records. The output produced by this markup is shown in Figure 10.


    Figure 10: Output generated by the code in Figure 9.

    LINQ is a new set of extensions in the .NET Framework 3.5 that encompass language-integrated data query, set, and transform operations. You can use LINQ queries or other objects (such as DataSet objects) instead of a data source control to bind data to the ListView control. Figure 11 shows the code to replace the LinqDataSource control used in Figure 9 with a LINQ query. You can keep the same markup for the templates.

     

    Protected Sub Page_Load(ByVal sender As Object,
    
     ByVal e As System.EventArgs)
    
       Dim dataContext As New NorthwindDataContext
    
    Dim countryName As String = Request.QueryString("Country")
    
       Dim employees = From f In dataContext.Employees _
    
                     Where f.Country = countryName
    
     EmployeesListView.DataSource = employees
    
     EmployeesListView.DataBind()
    
    End Sub

    Figure 11: Binding the ListView control to a LINQ query.

    The disadvantage of using the DataSource property instead of binding the control to a data source object is that this approach requires that you write code for any additional functionality, such as sorting, paging, deleting, and updating. In this case, you must add event handlers for the appropriate events.

     

    Using Events

    The ListView control provides many events for you to add functionality to your control or provide additional logic in response to the event. Figure 12 lists the main events that are provided by the ListView control.

     

    Event

    Description

    DataBinding/DataBound

    Occurs when/after the ListView control binds to a data source.

    ItemCanceling

    Occurs when a cancel operation is requested, but before the insert or edit operation is cancelled.

    ItemCommand

    Occurs when a button is clicked.

    ItemCreated

    Occurs when an item is created.

    ItemDataBound

    Occurs when a data item is bound to data.

    ItemDeleting/ItemDeleted

    Occurs when a delete operation is requested, but before/after the item is deleted.

    ItemEditing

    Occurs when an edit operation is requested, but before the item is put in edit mode.

    ItemInserting/ItemInserted

    Occurs when an insert operation is requested, but before/after the item is inserted into the data source.

    ItemUpdating/ItemUpdated

    Occurs when an update operation is requested, but before/after the item is updated in the data source.

    LayoutCreated

    Occurs when the LayoutTemplate template is created.

    PagePropertiesChanging/PagePropertiesChanged

    Occurs when the page properties change, before/after the control sets the new values.

    SelectedIndexChanging/SelectedIndexChanged

    Occurs when a select operation is requested, before/after the select operation is handled.

    Sorting/Sorted

    Occurs when a sort operation is requested, before/after the sort operation is handled.

    Figure 12: Main events provided by the ListView control.

     

    Figure 13 shows an example of a ListView control that consumes the ItemDataBound event; Figure 14 shows the code for the ItemDataBound event-handling method. The event-handling method accesses one of the controls inside the data item to verify if the stock is low. If the stock is low, the font color is changed to distinguish from the records that have a regular number of items in stock.

     

    
    
     
    
       

    Figure 13: A ListView control that consumes the ItemDataBound event.

     

    Protected Sub ListView1_ItemDataBound(ByVal sender As Object,
    
     ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
    
     'Obtain the item
    
     Dim UnitsLabel As Label =
    
       CType(e.Item.FindControl("UnitsInStockLabel"), Label)
    
     If (UnitsLabel.Text.Length > 0) Then
    
       'Check if the stock is low
    
       Dim units As Int16 = CType(UnitsLabel.Text, Int16)
    
       If (units < 15) Then
    
         'Display the value in red when the stock is low
    
         UnitsLabel.ForeColor = Drawing.Color.Red
    
       End If
    
     End If
    
    End Sub

    Figure 14: The event-handling method for the ItemDataBound event.

     

    Conclusion

    The ListView control might not be as innovative as other new features in the .NET Framework 3.5 such as LINQ or AJAX but it s a great data-bound control for you to use when you need complete control over the generated HTML markup or when you need all the common data operations combined in one single control.

    The files accompanying this article are available for download.

    Maira Wenzel, MCSD, is a Programming Writer in the ASP.NET User Education team. She has been extensively working with Microsoft technologies since 2000, including SQL Server, ASP.NET, C#, Visual Basic, and SharePoint Server.

    Hide comments

    Comments

    • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

    Plain text

    • No HTML tags allowed.
    • Web page addresses and e-mail addresses turn into links automatically.
    • Lines and paragraphs break automatically.
    Publish