Pages

Friday, November 11, 2011

GridView Examples for ASP.NET 2.0: Formatting the GridView


In the examples we've looked at so far, the GridView's output is a tad drab and unattractive. In Figure 7, for example, the GridView's output lacks any color. The text in the header of each column matches the DataSource field names exactly, like ProductName (without a space between Product and Name), whereas it would make more sense to display it as Product Name or perhaps just Product. We also might want to have the UnitPrice column formatted as a currency, and have its data right-aligned. Perhaps we want to reorder the columns, or only display a subset of the columns returned by the data source control. Or we may want to employ more advanced formatting, such as changing the background color of the GridView row if there are zero items in stock.
Fortunately, all of these tasks are easy to accomplish with the GridView, most of which can be accomplished through the Design view without a line of code. There's even an Auto Format wizard to help improve the aesthetics of the GridView for folks like me who have no artistic skills. In this section we'll look at how to format the GridView through properties that can be set through the Designer, how to format based upon the actual data bound to the GridView, and how to use skins to alter the appearance of the GridView.

Examining the GridView's Aesthetic Properties

Like the DataGrid in ASP.NET 1.x, the GridView contains a wealth of properties that can be set to gussy up the appearance of the GridView. Properties such asBackColorFont, and ForeColor allow you to dictate the aesthetics for the entire GridView. You can also specify aesthetic settings specific to particular parts of theGridView through the HeaderStyleRowStyleAlternatingRowStyleFooterStyle, and other properties. Additionally, styles can be set on a column-by-column basis, as well.
If you are an artistic person you can likely put together proper colors and styles that will provide the end user with an eye-pleasing GridView. If you are like me, though, the good news is that the GridView can be Auto Formatted to a variety of well put together styles. To take advantage of the Auto Formatting, simply click the Auto Format link in the GridView's Smart Tag, which will display the Auto Format dialog box (shown in Figure 11).
Aa479342.gridview_fg11(en-us,MSDN.10).gif
Figure 11
The Auto Format wizard only applies various colors designs to the GridView. If you want to adjust the GridView column appearances—such as formatting the data as a currency or center-aligning the data—simply click the Edit Columns link from the GridView's Smart Tag. This will display a dialog box listing all of theGridView's columns and their properties (see Figure 12).
Aa479342.gridview_fg12(en-us,MSDN.10).gif
Figure 12
The lower left-hand corner lists the columns in the GridView. From this dialog box you can adjust the ordering of the columns or remove or add columns altogether. To reorder the columns in the GridView, click on a column and then click on the up or down arrow to adjust its position in the column list. To remove a column from the GridView, select the column then click the X button to delete it.
When you click on one of the columns, its properties are listed in the pane on the right. From the ItemStyle property you can set formatting properties for the items of the column, such as how the data should be horizontally aligned, or if the data should be displayed in a bold font. You can change the text that appears in the header of the column through the HeaderText property. To format the data in the columns, use the DataFormatString property, setting it to {0:format string}. For example, to have the UnitPrice column formatted as a currency, I set the DataFormatString property to {0:c}.
Note   To learn more about the various possible values for format strings, refer to the Formatting Types section in the .NET Framework documentation.
Figure 13 shows a screenshot of a formatted GridView displaying data from the Products table. Notice that the text in the headers has been changed from their default values to more user-friendly values. The GridView has also been given some color (I used the Brown Sugar option in the Auto Format dialog box), the Price/Unit and Units In Stock columns' data is right-aligned, and the Price/Unit column's data has been formatted as a currency.
Aa479342.gridview_fg13(en-us,MSDN.10).gif
Figure 13
Changing the GridView's aesthetic properties through the Designer simply sets the declarative syntax to the appropriate values. The complete declarative syntax for the page is shown here:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
            <asp:SqlDataSource ID="productsDataSource" 
             Runat="server" 
             SelectCommand="SELECT [ProductID], [ProductName], 
               [QuantityPerUnit], [UnitPrice], [UnitsInStock] FROM 
               [Products]"
         ConnectionString="<%$ ConnectionStrings:NWConnectionString %>" 
         DataSourceMode="DataReader">
        </asp:SqlDataSource>
        <asp:GridView ID="productGridView" Runat="server" 
          DataSourceID="productsDataSource"
            DataKeyNames="ProductID" AutoGenerateColumns="False" 
             BorderWidth="1px" BackColor="#DEBA84" 
             CellPadding="3" CellSpacing="2" BorderStyle="None" 
             BorderColor="#DEBA84">
            <FooterStyle ForeColor="#8C4510" 
              BackColor="#F7DFB5"></FooterStyle>
            <PagerStyle ForeColor="#8C4510" 
              HorizontalAlign="Center"></PagerStyle>
            <HeaderStyle ForeColor="White" Font-Bold="True" 
              BackColor="#A55129"></HeaderStyle>
            <Columns>
                <asp:BoundField ReadOnly="True" HeaderText="ID" 
                  InsertVisible="False" DataField="ProductID"
                    SortExpression="ProductID">
                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
                </asp:BoundField>
                <asp:BoundField HeaderText="Name" 
                 DataField="ProductName" 
                 SortExpression="ProductName"></asp:BoundField>
                <asp:BoundField HeaderText="Qty/Unit" 
                 DataField="QuantityPerUnit" 
                 SortExpression="QuantityPerUnit"></asp:BoundField>
                <asp:BoundField HeaderText="Price/Unit" 
                DataField="UnitPrice" SortExpression="UnitPrice" 
                DataFormatString="{0:c}">
                    <ItemStyle HorizontalAlign="Right"></ItemStyle>
                </asp:BoundField>
                <asp:BoundField HeaderText="Units In Stock" 
                  DataField="UnitsInStock" 
                  SortExpression="UnitsInStock" 
                   DataFormatString="{0:d}">
                    <ItemStyle HorizontalAlign="Right"></ItemStyle>
                </asp:BoundField>
            </Columns>
            <SelectedRowStyle ForeColor="White" Font-Bold="True" 
             BackColor="#738A9C"></SelectedRowStyle>
            <RowStyle ForeColor="#8C4510" 
               BackColor="#FFF7E7"></RowStyle>
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Skinning the GridView

Two of the neat new features in ASP.NET 2.0 are Themes and Skins. A Skin is a file that defines the visual appearance of a particular control. You can create a Skin file for the GridView control that defines the look of the GridView for different SkinIDs. A Theme is a collection of Skins.
In order to start using Themes you must create a folder in the /app_themes directory of your Web application. Inside this directory, add a new folder for each Theme you want to create. In the download accompanying this article, there's a single folder in the /app_themes directory, GridViewTheme. Adding Skins to a Theme is as simple as adding a new file named WebControlToBeSkinned.skin in the Theme's directory (to provide a Skin for the GridView, name the fileGridView.skin). The Skin file should contain declarative syntax specifying the aesthetic markup for the GridView for various SkinIDs. As the file GridView.skinshows, I have created a default markup and a markup for two SkinIDs: Professional and Fun.
<asp:GridView runat="server" Font-Name="Arial" />
<asp:GridView runat="server" SkinID="Professional" Font-Name="Verdana"
                Font-Size="10pt" Cellpadding="4"
            HeaderStyle-BackColor="#444444"
            HeaderStyle-ForeColor="White"
                AlternatingRowStyle-BackColor="#dddddd" />
<asp:GridView runat="server" SkinID="Fun" Font-Name="Comic Sans MS"
                Font-Size="13pt" BackColor="Khaki"
                AlternatingRowStyle-BackColor="Tan"
            HeaderStyle-BackColor="SaddleBrown"
            HeaderStyle-ForeColor="White"
            HeaderStyle-Font-Bold="True"
            />

The default markup is listed at the top, and indicates that the GridView should be displayed with the Arial font. The next two sections indicate the markup that should be used for the SkinIDs Professional and Fun. For Professional, the Verdana font is used with a CellPadding of 4 and a dark gray header background with white text. Each alternating row color's background is set to a light gray. For Fun, the Comic Sans MS font is used, with a larger font size and a brownish background.
Finally, to Skin a GridView, simply add the Theme to use in the @Page directive and then set the GridView's SkinID appropriately. The following page specifies the Theme in the @Page directive and then displays three GridViews: one with no SkinID specified, one with the Professional SkinID, and one with the Fun SkinID.
<%@ Page Language="C#" StyleSheetTheme="GridViewTheme" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:SqlDataSource ID="productsSubsetDataSource" 
         Runat="server" SelectCommand="SELECT TOP 5 ProductID, 
           ProductName, UnitPrice FROM Products ORDER BY ProductName"
            ConnectionString=
             "<%$ ConnectionStrings:NWConnectionString %>">
        </asp:SqlDataSource>
        <h2>A GridViwe Without a Skin Specified</h2>
        <asp:GridView ID="GridView3" Runat="server" 
         DataSourceID="productsSubsetDataSource"
            DataKeyNames="ProductID" AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField ReadOnly="True" 
                  HeaderText="ProductID" InsertVisible="False" 
                  DataField="ProductID"
                    SortExpression="ProductID"></asp:BoundField>
                <asp:BoundField HeaderText="ProductName" 
                  DataField="ProductName" SortExpression="ProductName">
                </asp:BoundField>
                <asp:BoundField HeaderText="UnitPrice" 
                  DataField="UnitPrice" SortExpression="UnitPrice">
                </asp:BoundField>
            </Columns>
        </asp:GridView>
        <h2>A GridViwe With the <i>Professional</i> Skin</h2>
        <asp:GridView ID="GridView1" Runat="server" 
           DataSourceID="productsSubsetDataSource"
            DataKeyNames="ProductID" AutoGenerateColumns="False" 
            SkinID="Professional">
            <Columns>
                <asp:BoundField ReadOnly="True" HeaderText="ProductID" 
                  InsertVisible="False" DataField="ProductID"
                    SortExpression="ProductID"></asp:BoundField>
                <asp:BoundField HeaderText="ProductName" 
                 DataField="ProductName" SortExpression="ProductName">
                </asp:BoundField>
                <asp:BoundField HeaderText="UnitPrice" 
                   DataField="UnitPrice" SortExpression="UnitPrice">
                </asp:BoundField>
            </Columns>
        </asp:GridView>
        <h2>A GridViwe With the <i>Fun</i> Skin</h2>
        <asp:GridView ID="GridView2" Runat="server" 
             DataSourceID="productsSubsetDataSource"
             DataKeyNames="ProductID" AutoGenerateColumns="False" 
             SkinID="Fun">
            <Columns>
                <asp:BoundField ReadOnly="True" HeaderText="ProductID" 
                   InsertVisible="False" DataField="ProductID"
                    SortExpression="ProductID"></asp:BoundField>
                <asp:BoundField HeaderText="ProductName" 
                  DataField="ProductName" SortExpression="ProductName">
                </asp:BoundField>
                <asp:BoundField HeaderText="UnitPrice" 
                  DataField="UnitPrice" SortExpression="UnitPrice">
                </asp:BoundField>
            </Columns>
        </asp:GridView>
    
    </div>
    </form>
</body>
</html>

Figure 14 shows a screenshot of this page when viewed through a browser. Notice that the aesthetic formatting is applied to the three GridViews even though the corresponding settings aren't in the ASP.NET page's declarative syntax. Rather, the settings are being dynamically imported from the GridView Skin file for the specified Theme.
Aa479342.gridview_fg14(en-us,MSDN.10).gif
Figure 14

Formatting the GridView Based on the Underlying Data

In the two previous examples the GridView's formatting was specified statically. There are times, however, where you might want to alter the formatting based on the data in the GridView. For example, when listing product information you might want to draw the user's eye to products that are out of stock. One way to accomplish this would be to change the background color of those rows with a Units In Stock value of 0.
To accomplish this we need to inspect the data of each of the rows of the GridView and alter the row's BackColor property if the Units In Stock is 0. The GridViewoffers a RowDataBound event that fires once for each row after the row has been created and bound to the corresponding record of data from the data source control. We can create an event handler for this event that checks to see if Units In Stock is 0 and, if it is, set the BackColor property of the GridView row to Yellow.
To create an event handler for the GridView's RowDataBound event, go to the Design view, click on the GridView, and go to the Properties pane. From the Properties pane, click on the lightning bolt; this will list the GridView's events. Then, in the RowDataBound line, type in the name of the event handler you want to create (I named my event handler productsGridView_RowDataBound). Finally, enter in the following code into the event handler:
productsGridView_RowDataBound Event Handler (Visual Basic)
Sub productsGridView_RowDataBound(ByVal sender As Object, _
  ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
    If e.Row.RowType = DataControlRowType.DataRow Then
        'determine the value of the UnitsInStock field
        Dim unitsInStock As Integer =  _
          Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, _
          "UnitsInStock"))
        If unitsInStock = 0 Then
            ' color the background of the row yellow
            e.Row.BackColor = Drawing.Color.Yellow
        End If
    End If
End Sub
productsGridView_RowDataBound Event Handler (C#)
void productsGridView_RowDataBound(object sender, 
  GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // determine the value of the UnitsInStock field
        int unitsInStock = 
         Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, 
         "UnitsInStock"));
        if (unitsInStock == 0)
            // color the background of the row yellow
            e.Row.BackColor = Color.Yellow;
    }
}

The event handler starts by checking to see if we are working with a DataRow. Realize that the GridView's RowDataBound event handler fires for each of the rows being created, including the HeaderRow. However, the HeaderRow doesn't have a Units In Stock column with data associated with it, so we are only interested in working with DataRows. The UnitsInStock field from the data bound to the GridView row is obtained through a DataBinder.Eval() call, passing in the data bound to the GridView row (e.Row.DataItem) and the name of the field whose value we are interested in. Finally, a check is made to see if there are zero units in stock. If so, the BackColor property of the row is set to Yellow.
Figure 15 shows a screenshot of this example when viewed through a browser. Note that rows with zero units in stock are highlighted yellow.
Aa479342.gridview_fg15(en-us,MSDN.10).gif
Figure 15

No comments:

Post a Comment