COMP3121 SESSION 5: MORE DATA-LINKING AND FORMATTING The previous exercises used the GridView and DetailsView controls to display & insert product & customer data. While these controls make it easy to display, page through, sort, add, edit, and delete data, the appearance is a bit “boxy” and this would not impress potential customers. Appearance should be a consideration with any shopping website… although ass2 won’t be assessed specifically on look-and-feel, some expectation of something presentable will be assumed! For interacting more flexibly with data, the DataList & Repeater controls are useful. These render their content using templates rather than BoundFields, CheckBoxFields, ButtonFields, etc. Like GridView (if you didn’t notice when you used it, take another look…), DataList renders as an HTML <table>, but allows for multiple data source records to be displayed per table row. The Repeater, on the other hand, renders no additional markup than what is explicitly specified, and is therefore an ideal candidate for HTML coding when more precise control is needed. Repeater is therefore useful for customised page development and in particular, for the shopping cart! Also, although master pages have been used, there has yet to be an example of using Cascading Style Sheets for formatting purposes. The repeater exercise will address this omission. Exercise 5(a) Displaying Product Information with DataList As already stated, DataList’s rendered output depends upon templates rather than BoundFields, etc. However, it is designed to display a set of records rather than just one. To bind product information from a database to a DataList: 1. Open an existing solution and create a new .aspx page. Don’t bother with a site master for now… 2. Drag a DataList from the Toolbox onto the Designer. Quick look at code in source view. Now, back to design mode. From the DataList’s smart tag, add a new DataSource and configure it to use the access database, and all fields from the products table. Visual Studio automatically creates an ItemTemplate in the DataList that displays the name and value of each data field returned by the data source: RCH11 with thanks to Scott Mitchell 1 <asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID" DataSourceID="AccessDataSource1" EnableViewState="False"> <ItemTemplate> </ItemTemplate> </asp:DataList> <asp:AccessDataSource ID="AccessDataSource1" runat="server" DataFile="~/App_Data/productdata.mdb" SelectCommand="SELECT * FROM [Products]"> </asp:AccessDataSource> 3. Back to design mode… before specifying any DataList’s templates, the Designer displays the displayed data screen as a grey box. 4. Now choose item template, and then end template editing. The design now encompasses the design template. Take a look in source code mode. It should look, depending on fieldnames, something like: <asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID" DataSourceID="AccessDataSource1" EnableViewState="False"> <ItemTemplate> ProductID: <asp:Label ID="ProductIDLabel" runat="server" Text='<%# Eval("ProductID") %>' /><br /> Name: <asp:Label ID="ProductNameLabel" runat="server" Text='<%# Eval("ProductName") %>' /><br /> Description: <asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /><br /> CategoryID: <asp:Label ID="PriceLabel" runat="server" Text='<%# Eval("Price") %>'/> </ItemTemplate> </asp:DataList> 4. Look at the source code again – notice the locations of the code that will present the values of the datafields, within <ItemTemplate>. Unlike in GridView or DetailsView, the appearance of a DataList template can easily be improved to satisfy the needs of the design: e.g. it is possible to modify the code to: display only selected records without changing the underlying SQL query display the name in an <h4> heading and lay out the remaining fields using a <table> beneath the heading. Two options are therefore available to you for removing a field from the display, and inserting a table (design mode & code mode) (your choice…) RCH11 with thanks to Scott Mitchell 2 If using design mode: use the Tables menu to create the table and then populate the cells use the Edit Templates option in design view to create the product display (always a good option if you don’t feel comfortable writing code) and Table menu option to create the table and add the data Note: Label controls have been used in the code, with Text property assigned to the value of the databinding syntax. In practice, these could have been omitted altogether, typing in just the databinding syntax <%# Eval("CategoryName") %> instead of using: <asp:Label ID="CategoryNameLabel" runat="server" Text='<%# Eval("CategoryName") %>' /> (both have the same effect!) However, leaving in the Label Web controls provides an easier means for formatting the data based on the data, and the “simpler” solution complicates matters with “Edit Templates” in the Designer, which uses the full syntax. This complication only applies to DataList! The Repeater requires that the template’s contents be edited from Source view. Consequently, when creating Repeater templates the Label Web controls will be left out, and the much shorter eval statements will be appropriate. This is obviously quicker, if coding by hand. Exercise 5(b): Exploring other DataList Templates in DataList When a template is chosen in Design view, DataList adds the relevant HTML code. However, DataList templates are not bound to data so any databinding syntax that attempted to access bound data would return a blank string… However, these templates are useful for formatting, and, in addition to the ItemTemplate, the DataList supports six other optional templates: HeaderTemplate if provided, adds a header row to the output and is used to render this row AlternatingItemTemplate used to render alternating items SelectedItemTemplate used to render the selected item; the selected item is the item whose index corresponds to the DataList’s Selected Index property EditItemTemplate used to render the item being edited RCH11 with thanks to Scott Mitchell 3 SeparatorTemplate - adds a separator between each item and is used to render this separator FooterTemplate - adds a footer row to the output and is used to render this row 1. From the Designer, click on the Edit Templates link in the DataList’s smart tag, choosing the Header Template from the drop-down list, and type in the text after picking the Heading 3 option from the style dropdown list (on toolbar, showing “none” by default). This should display “Product Information” at the top in an <h3> heading. This could also have been hand coded by entering <HeaderTemplate> <h3>Product Information</h3> </HeaderTemplate> within the <asp:DataList> tags. 2. To add a bit of space between each product listing, choose a SeparatorTemplate, but don’t add any text yet. Now go back into source mode and create the effect of a line between each section, using the horizontal rule tag (<hr>): <SeparatorTemplate> <hr /> </SeparatorTemplate> Note: Like the HeaderTemplate and FooterTemplates, the SeparatorTemplate is not bound to any record from the data source and therefore cannot directly access the data source records bound to the DataList. 3. Now run the page. Note the header row and the line between each product listing. Try investigating templates a little further… e.g. add a footer template. Check the source code generated before running the page. One purpose of these exercises has been to introduce you to the syntax of the various templates, which DataList adds in the right place for you. The next exercise will involve the Repeater control which also uses templates but in a slightly more limited way. Exercise 5(c): The Repeater Control, and use of HTML The Repeater control is necessary if total control over the HTML is required. . As with DataList, formatting is based on templates (only five this time): HeaderTemplate if provided, adds the specified markup before the items ItemTemplate used to render items AlternatingItemTemplate if provided, used to render alternating items RCH11 with thanks to Scott Mitchell 4 SeparatorTemplate if provided, adds the specified markup between each item FooterTemplate - if provided, adds the specified markup after the items However, unlike DataLIst all of these templates need to be completely hard coded (P.S. or cut-and-pasted from a DataList control) 1. Now, begin another new .aspx page, and drag a repeater control within a div section. 2. Now, create a bulleted list. The good news (for those who don’t like to hard code) is that the toolbox also contains the BulletedList control, which can be bound to a data source control in order to display a simple bulleted list. Use this, and link the control with an appropriate data source. Simply indicate the data field to display as the text for each list item, and let the wizard do all the coding. Take a quick look in source mode, and then CTRL-F5 before moving on… 3. The Repeater serves as a “catch all data” Web control, which can be used where no other control can generate the code. For example, it is useful to choose the categories displayed in a single-row HTML <table> with each category displayed as a column in the table. This will be very useful when creating product pages with parameter passing as well as the shopping cart page. Now, go back to the previous .aspx page containing the DataList. Drag a Repeater control onto the page in design mode, above the Product Information DataList. Click on the smart tag: Choose Data Source. Opt to create a new DataSource and configure it to link to the products database as before… 4. Look at the code. Unlike the DataList, Visual Studio does not automatically create an ItemTemplate for the Repeater after binding it to a data source. Furthermore, the Repeater’s templates cannot be configured through the Designer and must be coded… Use table menu to produce a single row table with three columns. Add contents category 1, category 2, etc., to the cells and switch to code mode. The resulting table should look like: <table> <tr> <td>Category 1</td> <td>Category 2</td> <td>Category 3</td> </tr> </table> 5. To complete the display, the relevant templates have to be added manually in exactly the right places. This is very important, and easily messed up! Go to Source mode and type in the following syntax: RCH11 with thanks to Scott Mitchell 5 <asp:Repeater ID="Repeater1" runat="server" DataSourceID="AccessDataSource2" EnableViewState="False"> <HeaderTemplate> <table> <tr> </HeaderTemplate> <ItemTemplate> <td><%# Eval("CategoryName") %></td> </ItemTemplate> <FooterTemplate> </tr> </table> </FooterTemplate> </asp:Repeater> The Repeater generates the precise markup as specified by its templates. Note the structure carefully… unless you stick to this structure, compile errors will be generated when you create the pages that will build towards assignment 2. Exercise 5(d): Improving the Appearance of the Repeater via CSS & ItemTemplates The beauty of cascading style sheets is that they can be applied quite specifically with HTML code. In this exercise, an existing CSS will be added to your project, and then css styles will be added to the page in a controlled way to control the display of the bound data. 1. First of all copy the css file styles.css from my COMP3121 website to your project. 2. Now, it should be possible to use that css file to make the category columns alternate background colours by using different CSS classes for different table data (td) sections. To accomplish this, first “include” the css file to the project. Now, assign the RowStyle CSS class to each Repeater item and the AlternatingRowStyle CSS class to each alternating Repeater item through the use of ItemTemplate and AlternatingItemTemplate: <ItemTemplate> <td class="RowStyle"> <%# Eval("CategoryName") %> </td> </ItemTemplate> <AlternatingItemTemplate> <td class="AlternatingRowStyle"> <%# Eval("CategoryName") %> </td> </AlternatingItemTemplate> RCH11 with thanks to Scott Mitchell 6 3. Now add a header row to the output with the text “Product Categories”. The number of columns the resulting <table> will depend on the number of fields you have used and is unknown. Therefore, the simplest way to generate a header row that is guaranteed to span all columns is to use two nested <table>s. The first <table> will contain two rows the header row and a row that will contain the second, single-row <table> that has a column for each category in the system: <table> <tr> <th>Product Categories</th> </tr> <tr> <td> <table> <tr> <td>Category 1</td> <td>Category 2</td> <td>Category N</td> </tr> </table> </td> </tr> </table> 4. Now, try the following HeaderTemplate and FooterTemplate syntax: <asp:Repeater ID="Repeater1" runat="server" DataSourceID="AccessDataSource2" EnableViewState="False"> <HeaderTemplate> <table cellpadding="0" cellspacing="0" style="border: solid 1px black;"> <tr> <th class="HeaderStyle">Product Categories</th> </tr> <tr> <td> <table cellpadding="4" cellspacing="0"> <tr> </HeaderTemplate> <ItemTemplate> <td class="RowStyle"><%# Eval("CategoryName") %> </td> </ItemTemplate> <AlternatingItemTemplate> <td class="AlternatingRowStyle"> <%# Eval("CategoryName") %></td> </AlternatingItemTemplate> <FooterTemplate> </tr> </table> </td> </tr> </table> </FooterTemplate> </asp:Repeater> Save the file, and run to see if this achieves the desired effect: Category Columns alternating in Background colour and including a Header Row. This is an ambitious exercise that is intended to focus you on using The Repeater with templates and tables so you get the hang of the syntax. At this stage, it is more important that you get no syntax errors than you get a table structure that holds products in actual categories. RCH11 with thanks to Scott Mitchell 7 Summary The DataList or Repeater controls are more flexible than GridView and DetailsView because they can display a set of records using templates instead of BoundFields, CheckBoxFields, etc. The DataList renders as an HTML <table> that, by default, displays each data source record in a single table row, just like a GridView with a single TemplateField, but it does permit multiple records to be displayed per table row. The Repeater, on the other hand, strictly emits the markup specified in its templates; it does not add any additional markup and therefore is commonly used to display data in HTML elements other than a <table> (such as in a bulleted list). What Else to do… This Repeater exercise has prepared you for creating the shopping cart page. By the time of the week 6 practical (after study week, apart from getting assignment 1 completed), you should have: 1. designed your database complete with all four entities and appropriate attributes (you are doing yourself a favour here, because the logical data model is required for the write-up of assignment 2). 2. implemented this database in full on Access, by adding the new entities, adding fields as appropriate, and linking alike fields together to produce a full relational system. This database will be very useful to you, starting with week 6 practical. 3. deduced the fields that are essential for the shopping cart, and work out the SQL query that would be needed to extract those fields from your access database. Not much to do, then! You will then be ready to devote the rest of the semester to producing the web pages & code. For a start, try coding this… RCH11 with thanks to Scott Mitchell 8