Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
107
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

338 C H A P T E R 1 0 R I C H D ATA C O N T R O L S

<asp:BoundField DataField="Title" HeaderText="Title" /> <asp:BoundField DataField="City" HeaderText="City" />

</Columns>

</asp:GridView>

When you explicitly declare a bound field, you have the opportunity to set other properties. Table 10-2 lists these properties.

Table 10-2. BoundField Properties

Property

Description

DataField

The name of the field (for a row) or property (for an object) of the

 

data item that you want to display in this column.

DataFormatString

A format string that formats the field. This is useful for getting

 

the right representation of numbers and dates.

ApplyFormatInEditMode

If true, the format string will be used to format the value even

 

when it appears in a text box in edit mode. The default is false,

 

which means only the underlying normal will be used (1143.02

 

instead of $1,143.02).

FooterText, HeaderText, and

Sets the text in the header and footer region of the grid, if this

HeaderImageUrl

grid has a heater (ShowHeader is true) and Footer (ShowFooter

 

is true). The header is most commonly used for a descriptive

 

label such as the field name, while the footer can contain a

 

dynamically calculated value such as a summary (a technique

 

demonstrated in the section “Summaries in the GridView”

 

toward the end of this chapter). To show an image in the header

 

instead of text, set the HeaderImageUrl property.

ReadOnly

If true, the value for this column can’t be changed in edit mode.

 

No edit control will be provided. Primary key fields are often

 

read-only.

InsertVisible

If false, the value for this column can’t be set in insert mode. If

 

you want a column value to be set programmatically or based on

 

a default value defined in the database, you can use this feature.

Visible

If false, the column won’t be visible in the page (and no HTML

 

will be rendered for it). This property gives you a convenient way

 

to programmatically hide or show specific columns, changing

 

the overall view of the data.

SortExpression

An expression that can be appended to a query to perform a

 

sort based on this column. Used in conjunction with sorting, as

 

described in the “Sorting the GridView” section.

HtmlEncode

If true (the default), all text will be HTML encoded to prevent

 

special characters from mangling the page. You could disable

 

HTML encoding if you want to embed a working HTML tag (such

 

as a hyperlink), but this approach isn’t safe. It’s always a better

 

idea to use HTML encoding on all values and provide other

 

functionality by reacting to GridView selection events.

NullDisplayText

The text that will be displayed for a null value. The default is an

 

empty string, although you could change this to a hard-coded

 

value, such as “(not specified).”

ConvertEmptyStringToNull

If this is true, before an edit is committed all empty strings will

 

be converted to null values.

ControlStyle, HeaderStyle,

Configures the appearance for just this column, overriding the

FooterStyle, and ItemStyle

styles for the row. You’ll learn more about styles throughout this

 

chapter.

 

 

C H A P T E R 1 0 R I C H D ATA C O N T R O L S

339

If you don’t want to configure columns by hand, select the GridView, and click the ellipsis (…) next to the Columns property in the Properties window. You’ll see a Fields dialog box that lets you add, remove, and refine your columns (see Figure 10-1).

Figure 10-1. Configuring columns in Visual Studio

Now that you understand the underpinnings of the GridView, you’ve still only started to explore its higher-level features. In the following sections, you’ll tackle these topics:

Formatting: How to format rows and data values

Selecting: How to let users select a row in the GridView and respond accordingly

Sorting: How to dynamically reorder the GridView in response to clicks on a column header

Paging: How to divide a large result set into multiple pages of data, using both automatic and custom paging code

Templates: How to take complete control of layout, formatting, and editing by defining templates

Formatting the GridView

Formatting consists of several related tasks. First, you want to ensure that dates, currencies, and other number values are presented in the appropriate way. You handle this job with the DataFormatString property. Next, you’ll want to apply the perfect mix of colors, fonts, borders, and alignment options to each aspect of the grid, from headers to data items. The GridView supports these features through styles. Finally, you can intercept events, examine row data, and apply formatting to specific data points programmatically. In the following sections, you’ll consider each of these techniques.

The GridView itself also exposes several formatting properties that are self-explanatory and aren’t covered here. These include GridLines (for adding or hiding table borders), CellPadding and CellSpacing (for controlling the overall spacing between cells), and Caption and CaptionAlign (for adding a title to the top of the grid).

340 C H A P T E R 1 0 R I C H D ATA C O N T R O L S

Tip Want to create a GridView that scrolls—inside a web page? It’s easy. Just place the GridView inside a Panel control, set the appropriate size for the panel, and set the Panel.Scrollbars to Auto, Vertical, or Both.

Formatting Fields

Each BoundField column provides a DataFormatString property that you can use to configure the appearance of numbers and dates using a format string.

Format strings are generally made up of a placeholder and format indicator, which are wrapped inside curly brackets. A typical format string looks something like this:

{0:C}

In this case, the 0 represents the value that will be formatted, and the letter indicates a predetermined format style. In this case, C means currency format, which formats a number as a dollar figure (so 3400.34 becomes $3,400.34). Here’s a column that uses this format string:

<asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:C}" />

Table 10-3 shows some of the other formatting options for numeric values.

Table 10-3. Numeric Format Strings

Type

Format String

Example

Currency

{0:C}

$1,234.50

 

 

Brackets indicate negative values: ($1,234.50).

 

 

Currency sign is locale-specific: (?1,234.50).

Scientific (Exponential)

{0:E}

1.234.50E+004

Percentage

{0:P}

45.6%

Fixed Decimal

{0:F?}

Depends on the number of decimal places you

 

 

set. {0:F3} would be 123.400. {0:F0} would be 123.

 

 

 

You can find other examples in the MSDN Help. For date or time values, there is also an extensive list. For example, if you want to write the BirthDate value in the format month/day/year (as in 12/30/05), you use the following column:

<asp:BoundField DataField="BirthDate" HeaderText="Birth Date" DataFormatString="{0:MM/dd/yy}" />

Table 10-4 shows some more examples.

Table 10-4. Time and Date Format Strings

Type

Format String

Example

Short Date

{0:d}

M/d/yyyy

 

 

(for example: 10/30/2005)

Long Date

{0:D}

dddd, MMMM dd, yyyy

 

 

(for example: Monday, January 30, 2005)

Long Date and Short Time

{0:f}

dddd, MMMM dd, yyyy HH:mm aa

 

 

(for example: Monday, January 30, 2005

 

 

10:00 AM)

C H A P T E R 1 0 R I C H D ATA C O N T R O L S

341

Type

Format String

Example

Long Date and Long Time

{0:F}

dddd, MMMM dd, yyyy HH:mm:ss aa

 

 

(for example: Monday, January 30, 2005

 

 

10:00:23 AM)

ISO Sortable Standard

{0:s}

yyyy-MM-dd HH:mm:ss

 

 

(for example: 2005-01-30 10:00:23)

Month and Day

{0:M}

MMMM dd

 

 

(for example: January 30)

General

{0:G}

M/d/yyyy HH:mm:ss aa (depends on locale-

 

 

specific settings)

 

 

(for example: 10/30/2002 10:00:23 AM)

 

 

 

The format characters are not specific to the GridView. You can use them with other controls, with data-bound expressions in templates (as you’ll see later in this chapter), and as parameters for many methods. For example, the Decimal and DateTime types expose their own ToString() methods that accept a format string, allowing you to format values manually.

Styles

The GridView exposes a rich formatting model that’s based on styles. Altogether, you can set eight GridView styles, as described in Table 10-5.

Table 10-5. Numeric Format Strings

Style

Description

HeaderStyle

Configures the appearance of the header row that contains column

 

titles, if you’ve chosen to show it (if ShowHeader is true).

RowStyle

Configures the appearance of every data row.

AlternatingRowStyle

If set, applies additional formatting to every other row. This formatting

 

acts in addition to the RowStyle formatting. For example, if you set a

 

font using RowStyle, it is also applied to alternating rows, unless you

 

explicitly set a different font through the AlternatingRowStyle.

SelectedRowStyle

Configures the appearance of the row that’s currently selected.

 

This formatting acts in addition to the RowStyle formatting.

EditRowStyle

Configures the appearance of the row that’s in edit mode.

 

This formatting acts in addition to the RowStyle formatting.

EmptyDataRowStyle

Configures the style that’s used for the single empty row in the special

 

case where the bound data object contains no rows.

FooterStyle

Configures the appearance of the footer row at the bottom of the

 

GridView, if you’ve chosen to show it (if ShowFooter is true).

PagerStyle

Configures the appearance of the row with the page links, if you’ve

 

enabled paging (set AllowPaging to true).

 

 

Styles are not simple single-value properties. Instead, each style exposes a Style object that includes properties for choosing colors (ForeColor and BackColor), adding borders (BorderColor, BorderStyle, and BorderWidth), sizing the row (Height and Width), aligning the row (HorizontalAlign and VerticalAlign), and configuring the appearance of text (Font and Wrap). These style properties allow you to refine almost every aspect of an item’s appearance. And if you don’t want to

342 C H A P T E R 1 0 R I C H D ATA C O N T R O L S

hard-code all the appearance settings in the web page, you can set the CssClass property of the style object reference to a stylesheet class that’s defined in a linked stylesheet (see Chapter 15 for more about styles).

Defining Styles

When setting style properties, you can use two similar syntaxes (and you’ll see both of them in this chapter). First, you can use the object-walker syntax to indicate the extended style properties as tag attributes. Here’s an example:

<asp:GridView runat="server" ID="grid" ItemStyle-ForeColor="DarkBlue" ... />

...

</asp:GridView>

Alternatively, you can add nested tags, as shown here:

<asp:GridView runat="server" ID="grid" ...> <ItemStyle ForeColor="DarkBlue" ... />

...

</asp:GridView>

Both of these approaches are equivalent. However, you make one other decision when setting style properties. You can specify global style properties that affect every column in the grid (as in the previous examples), or you can define column-specific styles. To create a column-specific style, you need to add style attributes or a nested tag inside the appropriate column tag, as shown here:

<asp:GridView runat="server" ID="grid" ...> <Columns>

<asp:BoundField DataField="EmployeeID" HeaderText="ID" ItemStyle-Width="30px" />

...

</Columns>

</asp:GridView>

Or equivalently, you can use a nested tag:

<asp:GridView runat="server" ID="grid" ...> <Columns>

<asp:BoundField DataField="EmployeeID" HeaderText="ID"> <ItemStyle Width="30px">

</asp:BoundField>

...

</Columns>

</asp:GridView>

This technique is often used to define specific column widths. If you don’t define a specific column width, ASP.NET makes each column just wide enough to fit the data it contains (or, if wrapping is enabled, to fit the text without splitting a word over a line break). If values range in size, the width is determined by the largest value or the width of the column header, whichever is larger. However, if the grid is wide enough, you might want to expand a column so it doesn’t appear to be crowded against the adjacent columns. In this case, you need to explicitly define a larger width.

Here’s a fully formatted GridView tag:

<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceEmployees" Font-Names="Verdana" Font-Size="X-Small" ForeColor="#333333" CellPadding="4" GridLines="None" AutoGenerateColumns="False">

<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /> <RowStyle BackColor="#FFFBD6" ForeColor="#333333" /> <AlternatingRowStyle BackColor="White" />

C H A P T E R 1 0 R I C H D ATA C O N T R O L S

343

<Columns>

<asp:BoundField DataField="EmployeeID" HeaderText="ID"> <ItemStyle Font-Bold="True" BorderWidth="1" />

</asp:BoundField>

<asp:BoundField DataField="FirstName" HeaderText="First Name" /> <asp:BoundField DataField="LastName" HeaderText="Last Name" /> <asp:BoundField DataField="City" HeaderText="City">

<ItemStyle BackColor="LightSteelBlue" /> </asp:BoundField>

<asp:BoundField DataField="Country" HeaderText="Country"> <ItemStyle BackColor="LightSteelBlue" />

</asp:BoundField>

<asp:BoundField DataField="BirthDate" HeaderText="Birth Date" DataFormatString="{0:MM/dd/yyyy}" />

<asp:BoundField DataField="Notes" HeaderText="Notes"> <ItemStyle Wrap="True" Width="400"/>

</asp:BoundField>

</Columns>

</asp:GridView>

This example uses GridView properties to set the font and adjust the cell spacing and cell gridlines. It uses styles to bold headings and configure the background of rows and alternating rows. Additionally, column-specific style settings highlight the location information with a different background, bold the ID values, and explicitly size the Notes column. A DataFormatString is used to format all date values in the BirthDate field. Figure 10-2 shows the final result.

Figure 10-2. A formatted GridView

344 C H A P T E R 1 0 R I C H D ATA C O N T R O L S

Configuring Styles with Visual Studio

There’s no reason to code style properties by hand in the GridView control tag, because the GridView provides rich design-time support. To set style properties, you can use the Properties window to modify the style properties. For example, to configure the font of the header, expand the HeaderStyle property to show the nested Font property, and set that. The only limitation of this approach is that it doesn’t allow you to set a style for individual columns—if you need that trick, you must first call up the Fields dialog box (shown in Figure 10-1) by editing the Columns property. Then, select the appropriate column, and set the style properties accordingly.

You can even set a combination of styles using a preset theme by clicking the Auto Format link in the GridView smart tag. Figure 10-3 shows the Auto Format dialog box with some of the preset styles you can choose. Select Remove Formatting to clear all the style settings.

Figure 10-3. Automatically formatting a GridView

Once you’ve chosen a theme, the style settings are inserted into your GridView tag, and you can tweak them by hand or by using the Properties window.

Formatting-Specific Values

The formatting you’ve learned so far isn’t that fine-grained. At its most specific, this formatting applies to a single column of values. But what if you want to change the formatting for a specific row, or even just a single cell?

The solution is to react to the GridView.RowCreated event. This event is raised when a part of the grid (the header, footer, or pager or a normal, alternate, or selected item) is being created. You can access the current row as a GridViewRow control. The GridViewRow.DataItem property provides the data object for the given row, and the GridViewRow.Cells collection allows you to retrieve the row content. You can use the GridViewRow to change colors and alignment, add or remove child controls, and so on.

The following example handles the RowCreated event and sets the colors according to the following rules:

C H A P T E R 1 0 R I C H D ATA C O N T R O L S

345

The item’s background color is set to pink and the foreground color is set to maroon if the title of courtesy is a title for a female—in this case Ms. or Mrs.

The item’s background color is set to dark blue and the foreground color is set to light cyan if the title of courtesy is Mr.

For other generic titles such as Dr., the item is rendered with the background color specified by the DataGrid.BackColor property.

Here is the complete code for the RowCreated event handler that implements these rules:

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)

{

if (e.Row.RowType == DataControlRowType.DataRow)

{

// Get the title of courtesy for the item that's being created.

string title = (string)DataBinder.Eval(e.Row.DataItem, "TitleOfCourtesy");

//If the title of courtesy is "Ms.", "Mrs.", or "Mr.",

//change the item's colors.

if (title == "Ms." || title == "Mrs.")

{

e.Row.BackColor = System.Drawing.Color.LightPink; e.Row.ForeColor = System.Drawing.Color.Maroon;

}

else if (title == "Mr.")

{

e.Row.BackColor = System.Drawing.Color.LightCyan; e.Row.ForeColor = System.Drawing.Color.DarkBlue;

}

}

}

First, the code checks if the item being created is an item or an alternate item. If neither of these, it means that the item is another interface element, such as the pager, footer, or header, and the procedure does nothing. If the item is of the right type, the code extracts the TitleOfCourtesy field from the data bound item and compares it to some hard-coded string values.

Figure 10-4 shows the resulting page.

Figure 10-4. Formatting individual rows based on values

346 C H A P T E R 1 0 R I C H D ATA C O N T R O L S

Tip This example uses the DataBinder.Eval() method to retrieve a piece of information from the data item using reflection. Alternatively, you could cast the e.Row.DataItem to the correct type (such as EmployeeDetails for the ObjectDataSource), DataRowView (for the SqlDataSource in DataSet mode), or DbDataRecord (for the SqlDataSource in DataReader mode). However, the DataBinder.Eval() approach works in all these scenarios (at the cost

of being slightly slower).

This isn’t the most useful example of using the RowCreated event, but it demonstrates how you can handle the event and read all the important information for the item. You could use much more imaginative formatting to change the way the pager’s links are represented, add new buttons to the pager or header, render values that you want to highlight with special fonts and colors, create total and subtotal rows, and more.

GridView Row Selection

Selecting a row means that the user can highlight or change the appearance of a row by clicking some sort of button or link. When the user clicks the button, not only will the row change its appearance, but also your code will have the opportunity to handle the event.

The GridView provides built-in support for selection. You simply need to add a CommandField column with the ShowSelect property set to true. The CommandField can be rendered as a hyperlink, a button, or a fixed image. You choose the type using the ButtonType property. You can then specify the text through the SelectText property or specify the link to the image through the SelectImageUrl property.

Here’s an example that displays a select button:

<asp:CommandField ShowSelectButton="True" ButtonType="Button" SelectText="Select" />

And here’s an example that shows a small clickable icon:

<asp:CommandField ShowSelectButton="True" ButtonType="Image" SelectImageUrl="select.gif" />

Figure 10-5 shows both types of select buttons. Clicking either one selects the row.

When you click a select button, the page is posted back, and a series of steps unfolds. First, the GridView.SelectedIndexChanging event fires, which you can intercept to cancel the operation. Next, the GridView.SelectedIndex property is adjusted to point to the selected row. Finally, the GridView.SelectedIndexChanged event fires, which you can handle if you want to manually update other controls to reflect the new selection. When the page is rendered, the selected row is given the SelectedRowStyle.

Note For selection to work, you must configure the SelectedRowStyle so that selected rows look different from normal rows. Usually, selected rows will have a different BackColor property.

Using Selection to Create a Master-Details Form

As demonstrated in the previous chapter, you can bind other data sources to a property in a control using parameters. For example, you could add two GridView controls and use information from the first GridView to perform a query in the second.

C H A P T E R 1 0 R I C H D ATA C O N T R O L S

347

Figure 10-5. GridView selection

In the case of the GridView, the property you need to bind is SelectedIndex. However, this has one problem. SelectedIndex returns a zero-based index number representing where the row occurs in the grid. This isn’t the information you need to insert into the query that gets the related records. Instead, you need a key field from the corresponding row.

Fortunately, the GridView makes it easy to retrieve this information using the SelectedDataKeys property. To use this feature, you must set the GridView.DataKeyNames property, with a comma-separated list of one or more key fields. Each name you supply must match one of the properties of the bound object or one of the fields of the bound record.

Usually, you’ll have only one key field, as shown here:

<asp:GridView ID="gridEmployees" runat="server" DataSourceID="sourceEmployees" DataKeyNames="EmployeeID" ... >

Now you can bind the second data source to this field. Here’s an example that uses the EmployeeID in a join query to find all the matching records from the Territories table:

<asp:SqlDataSource ID="sourceRegions" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"

ProviderName="System.Data.SqlClient" SelectCommand="SELECT Employees.EmployeeID, Territories.TerritoryID, Territories.TerritoryDescription FROM Employees INNER JOIN EmployeeTerritories ON Employees.EmployeeID = EmployeeTerritories.EmployeeID

INNER JOIN Territories ON EmployeeTerritories.TerritoryID = Territories.TerritoryID WHERE (Employees.EmployeeID = @EmployeeID)" >

<SelectParameters>

<asp:ControlParameter ControlID="gridEmployees" Name="EmployeeID" PropertyName="SelectedDataKey.Values["EmployeeID"]" /> </SelectParameters>

</asp:SqlDataSource>