Data Display and Edit Controls






Data Display and Edit Controls

In the previous chapter you saw how easy it was to configure a grid to use a data source control to not only display the data, but to also provide editing. These topics are worthy of discussion in more detail, and the following common scenarios will be covered:

  • How to bind controls to sources of data

  • Which controls to use to display data

  • How to allow custom editing of the data

  • How to customize the display controls

The methods of handling these questions are similar for many of the controls, so you'll find it easy to switch between them.

Data Binding to Data Source Controls

Along with the declarative style of setting the SqlDataSource control, the new grid and edit controls provide a DataSourceID property, which can be set to the ID of the data source. This automatically links the two controls, so that when the page is loaded, the data is fetched and displayed automatically. For example:

<asp:SqlDataSource ID="SqlDataSource1" runat="server"
  ...
</asp:SqlDataSource>

<asp:GridView ID="GridView1" runat="server"
  DataKeyNames="ProductID"
  DataSourceID="SqlDataSource1"></asp:GridView>

The DataKeyNames property identifies the unique key of the underlying data; it isn't required for displaying data, but it is required when you use the grid for updating data. The GridView will automatically display all columns supplied to it, but by default provides a read-only view. To enable modification, you can use the properties on the GridView Tasks pane, as shown in Figure.

8. GridView Tasks pane


Enabling editing and deleting adds a custom column to the grid.

<asp:GridView ID="GridView1" runat="server"
  DataKeyNames="ProductID"
  DataSourceID="SqlDataSource1">
  <Columns>
    <asp:CommandField ShowDeleteButton="True"
                      ShowEditButton="True" />
  </Columns>
</asp:GridView>

The common task doesn't have an option to enable new rows, and although there is a ShowInsertButton property, the grid itself doesn't support the notion of a new row; you don't get a blank row into which you can add your new data. There are ways to overcome this with the grid if required, but a far better solution is to use a DetailsView or FormView control, which is where the ShowInsertButton is primarily used. The DetailsView and FormView controls are covered later in the chapter.

Setting the ShowDeleteButton and ShowEditButton to true automatically gives edit and delete functionality, as shown in Figure. When the Edit button is selected, the row automatically switches to edit mode, with text boxes for editing the columns. Clicking Update automatically sends the changes back to the data source, which in turn sends them back to the SQL table.

9. A GridView in edit mode


No code is required to enable editing and deleting within a grid. When the Update link is clicked, the column values are passed into the parameters of the SqlDataSource and the UpdateCommand is executed. If the Cancel link is clicked, the current values are ignored and the Update-Command is not run.

Customizing the GridView Control

The look shown in Figure is the default look and behavior for a GridView control, but you can achieve complete flexibility by customizing the control.

Adding a Custom Pager

Screen real estate is always a problem, especially when displaying tables of data. This is solved by paging the data, so that a limited number of rows are shown at once. Paging is easily achieved by setting the AllowPaging property to true, and optionally the PageSize property to the number of rows to show (this defaults to 10). Adding paging will, by default, place an additional row at the bottom of the grid with the page numbers, as shown in Figure.

10. The default pager


The pager can be customized in two ways. The first is to use the PagerSettings element, the general declaration of which is shown in Listing 3.5.

The PagerSettings Element

<PagerSettings
  FirstPageImageUrl="String"
  FirstPageText="String"
  LastPageImageUrl="String"
  LastPageText="String"
  Mode="NextPrevious|NextPreviousFirstLast|Numeric|NumericFirstLast"
  NextPageImageUrl="String"
  NextPageText="String"
  PageButtonCount="Integer"
  Position="Bottom|Top|TopAndBottom"
  PreviousPageImageUrl="String"
  PreviousPageText="String" />

The PageButtonCount property defines how many page numbers are shown, and if set to a value lower than the actual number of pages, ellipses are shown to indicate there are more pages.

The pager can be set to show text instead of page numbers by using the Mode property, and when done that way, the PageText properties define the text to show. These default to <<, <, >, and >>, but you can set them to any text you like, as shown in Listing 3.6.

Setting the Pager Text Links

<PageSettings
  Mode="NextPreviousFirstLast"
  FirstPageText="First"
  LastPageText="Last"
  NextPageText="Next"
  PreviousPageText="Previous" />

As an alternative, you can set the ImageUrl properties, which will display image links instead of text links.

You can perform further customization by templating the pager, by using the PagerTemplate subelement. Within the PagerTemplate, you can add any content, including server controls. For example, instead of page numbers of Next/Previous buttons, you could place a DropDownList containing the pages.

Defining Columns

If you don't want to accept the automatic generation of columns, you can set the AutoGenerateColumns property to False and use the Columns subelement to define your own. The advantage of this is that you can define how the columns appear in both display and edit modes, as opposed to the default types used by the grid. In default mode, labels are used for displaying data, and a TextBox is used in edit mode for strings, and a CheckBox for bit columns. Instead of using this default, you can use the following controls:

  • BoundField, which acts like a default column, displaying text in display mode, and a TextBox in edit mode

  • ButtonField, which displays a button in each row. The button can be a standard Button, a LinkButton, or an ImageButton

  • CheckBoxField, which displays bit data as a CheckBox

  • CommandField, which can display a text link, buttons, or image buttons to use for issuing commands on the grid. The commands can be standard ones to switch between display and edit mode, in which case the standard set of commands are displayed (Select, Edit, Delete, Insert, and Cancel), or custom commands to perform custom actions in the button event handler

  • HyperLinkField, which displays a HyperLink control

  • ImageField, which displays an Image control

  • TemplateField, which provides a custom area for content

There are different types of templates for different states, and these are covered in more detail in the Template Columns section.

The BoundField Control

The BoundField control displays as text in display mode, and as a TextBox in edit mode. The field to display is set with the DataField property, while the DataFormatString property can be used to format the value. For example, displaying a currency value can be done by setting DataFormatString to {0:C}. Listing 3.7 shows the outline syntax for the BoundField control.

Syntax of the BoundField Control

<asp:BoundField
  DataField="String"
  DataFormatString="String"
  ApplyFormatInEditMode="[True|False]"
  ConvertEmptyStringToNull="[True|False]"
  NullDisplayText="String"
  HtmlEncode="[True|False]"
  ReadOnly="[True|False]"
  Visible="[True|False]"
  InsertVisible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  ControlStyle-[PropertyName]="[value]"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

A description of these properties can be seen in Figure.

Properties of the BoundField Control

Property/Attribute

Description

DataField

Sets or returns a String that is the name of the column in the source rows that will provide the data to display in this column of the grid.

DataFormatString

Sets or returns a String that contains the formatting details for the value displayed in this column.

ApplyFormatInEditMode

Sets or returns a Boolean value that indicates whether the formatting applied by the DataFormatString property when in "normal" mode will also be applied in "edit" mode; for example, displaying a currency symbol and trailing zeros in the text box in edit mode rather than just the numeric value.

ConvertEmpty StringToNull

Sets or returns a Boolean value that indicates whether an empty string in this column should be treated as null. This is useful when editing the data if the data source expects null values to be used when no value is present.

NullDisplayText

Sets or returns a String that is the text to display in the grid for rows that have a null value in this column.

HtmlEncode

Sets or returns a Boolean value that indicates whether are the values in this column will be HTML-encoded before they inserted into the output generated by the GridView control.

ReadOnly

Sets or returns a Boolean value that indicates whether the values in this column can be edited. If True, the column will not display a text box in edit mode.

Visible

Sets or returns a Boolean value that indicates whether this column is visible within the output generated by the grid control.

Insert Visible

Sets or returns a Boolean value that indicates whether this column is visible when the grid is in insert mode.

SortExpression

Sets or returns a String that defines the sort expression for this column, as a comma-delimited list of column names.

ShowHeader

Sets or returns a Boolean value that indicates whether the header for this column will be displayed.

HeaderText

Sets or returns a String that is the text to display in the header row for this column.

Accessible HeaderText

Sets or returns a String that sets the value of the HTML abbr attribute of the <th> elements that display the column headings when this column is rendered. Non-visual page reader applications and specialist user agents use the abbr attribute to assist in determining the layout of a table.

ControlStyle

Returns a reference to a Style instance that describes the style and formatting of any server controls displayed in the row.

HeaderStyle

Returns a reference to a TableItemStyle instance that describes the style and formatting of the header for this column.

HeaderImageUrl

Sets or returns a String that is the relative or absolute URL of an image to display in the header row for this column.

ItemStyle

Returns a reference to a TableItemStyle instance that describes the style and formatting of the values in the data-bound rows in this column.

FooterText

Sets or returns a String that is the text to display in the footer row for this column.

FooterStyle

Returns a reference to a TableItemStyle instance that describes the style and formatting of the footer for this column.


The ButtonField Control

The ButtonField control is for when you need a button or link in the column to cause a page postback, perhaps to indicate that more details for the row are to be shown, or to perform an action on the row, such as editing. A ButtonField control can be a standard button, a link button, or an image button. Listing 3.8 shows the outline syntax of the ButtonField control.

Syntax of the ButtonField Control

<asp:ButtonField
  ButtonType="[Button|Image|Link]"
  CommandName="String"
  DataTextField="String"
  DataTextFormatString="String"
  CausesValidation="[True|False]"
  ValidationGroup="String"
  Text="String"
  ImageUrl="String"
  ApplyFormatInEditMode="[True|False]"
  HtmlEncode="[True|False]"
  Visible="[True|False]"
  InsertVisible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  ControlStyle-[PropertyName]="[value]"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

The properties in bold are specific to the ButtonField control and are described in Figure, while the others are the same as for the BoundField control.

Properties of the ButtonField Control

Property/Attribute

Description

ButtonType

Sets or returns a value from the ButtonType enumeration (Button, Image, or Link) that specifies the type of control to create in each row for this column. The default is Link.

CommandName

Sets or returns a String value that is the CommandName property of the button in each row of the output.

DataTextField

Sets or returns a String that indicates the name of the column within the source data that will supply the value for the Text property of the control (the caption of a button or the text of a link).

DataTextFormatString

Sets or returns a String that contains the formatting information for the value in the row. Uses the same syntax as the DataFormatString property described for the BoundField control, using {0} as a placeholder.

CausesValidation

Sets or returns a Boolean value that indicates whether the button will cause any validation controls in the page to validate their values and report any errors. The default is true.

ValidationGroup

Sets or returns a String that is the name of the group of validation controls that this button will be a member of. See Chapter 9 for more details about validation groups.

Text

Sets or returns a String that will be used in place of DataTextField, in other words, the static value for the caption or text of the link that is the same for every row.

ImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display when the ButtonType property is set to Image.


The CheckBoxField Control

The CheckBoxField control is used to display a checkbox, which reflects the Boolean value from the underlying data, such as a bit column from SQL Server. Listing 3.9 shows the outline syntax for the CheckBoxField control.

Syntax of the CheckBoxField Control

<asp:CheckBoxField
  DataField="String"
  DataFormatString="String"
  NullDisplayText="String"
  ReadOnly="[True|False]"
  Text="String"
  ApplyFormatInEditMode="[True|False]"
  HtmlEncode="[True|False]"
  InsertVisible="[True|False]"
  Visible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  AccessibleHeaderText="String"
  HeaderText="String"
  ControlStyle-[PropertyName]="[value]"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

The property in bold is specific to the CheckBoxField control and is described in Figure, while the others are the same as those for the BoundField control.

Properties of the CheckBoxField Control

Property/Attribute

Description

Text

Sets or returns a String that will be used as the Text property of the CheckBox control.


The HyperLinkField Control

The HyperLinkField control is used to display a clickable link in each row using a standard HTML <a> element. The text and link reference can be set as static text or bound to columns from the underlying data. Listing 3.10 shows the outline syntax for the HyperLinkField control.

Syntax of the HyperLinkField Control

<asp:HyperLinkField
  DataTextField="String"
  DataTextFormatString="String"
  Text="String"
  DataNavigateUrlFields="String[,String]"
  DataNavigateUrlFormatString="String"
  NavigateUrl="String"
  Target="String"
  ApplyFormatInEditMode="[True|False]"
  HtmlEncode="[True|False]"
  Visible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  ControlStyle-[PropertyName]="[value]"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

The properties in bold are specific to the HyperLinkField control and are described in Figure while the others are the same as for the BoundField control.

Properties of the HyperLinkField control

Property/Attribute

Description

DataTextField

Sets or returns a String that indicates the name of the column within the source data that will supply the value for the Text property of the control (the visible text of the link).

DataTextFormatString

Sets or returns a String that contains the formatting information for the bound value that is applied to the Text property of the link.

Text

Sets or returns a String that will be used in place of DataTextField, in other words, the static value for the text of the link that is the same for every row.

DataNavigateUrlFields

Sets or returns a String Array that specifies the names of the columns within the source data that will supply values for the NavigateUrl property of the control (the href attribute of the resulting <a> element). Use a comma-delimited list of column names when declaring the control. This means that you can use values from different columns for hyperlinks. See the next section, Using the DataNavigateUrlFields Property.

DataNavigateUrlFormatString

Sets or returns a String that contains the formatting information for the bound values that will be applied to the NavigateUrl property.

NavigateUrl

Sets or returns a String that will be used in place of DataNavigateUrlFields, in other words, the static value for the href of the links that is the same for every row.

Target

Sets or returns a String that is the name of the target window for the link and will be used as the target attribute of the resulting <a> element.


Using the DataNavigateUrlFields Property

You can specify more than one column for the DataNavigateUrlFields property or attribute of a grid-type control. When the GridView binds a HyperlinkField to its source data, all the columns declared for the DataNavigateUrlFields property can be used within the DataTextFormatString property to provide more than one HRef value for the hyperlinks. For example, you can declare a HyperlinkField like this:

<asp:HyperLinkField DataTextField="ProductName"
  DataNavigateUrlFields="ProductID,ProductName"
  DataNavigateUrlFormatString=
    "http://www.mysite.com/products?product={0}" />

In this case, for a row containing the product named Chang with ProductID value 2, the href value will appear as:

http://www.mysite.com/products?product=2

However, you can also declare the DataNavigateUrlFormatString as:

DataNavigateUrlFormatString=
  "http://www.mysite.com/products?product={1}" />

In this case, the href value for the same row will appear as:

http://www.mysite.com/products?product=Chang

The same effect can be obtained, of course, by changing the value of the DataNavigateUrlFormatString property at runtime in the Item-DataBound event, just as you would with one of the v1.x grid or list controls.

However, the most useful feature of all, and one that was much requested by users, is that the DataNavigateUrlFormatString can now contain more than one placeholder, for example:

DataNavigateUrlFormatString=
  "http://www.mysite.com/products?product={0}&&name={1}" />

The href value for the same row will now appear as:

http://www.mysite.com/products?product=2&name=Chang

This gives you the opportunity to easily create HRef values that contain multiple query string parameters. Just remember to use the HTML-encoded ampersand (&amp;) to concatenate them together, as shown.

The ImageField Control

The ImageField control is used to display images, using the underlying data to provide the URL for the image. Listing 3.11 shows the outline syntax for the ImageField control.

The properties in bold are specific to the ImageField control and are described in Figure, while the others are the same as those for the BoundField control.

Properties of the ImageField Control

Property/Attribute

Description

DataImageUrlField

Sets or returns a String that indicates the name of the column within the source data that will supply the value for the ImageUrl property of the image control.

DataImageUrl FormatString

Sets or returns a String that contains the formatting information for the bound value that is applied to the Url property of the image.

DataAlternate TextField

Sets or returns a String that indicates the name of the column within the source data that will supply the value for the AlternateText property of the image control.

DataAlternateTextFormatString

Sets or returns a String that contains the formatting information for the bound value that is applied to the AlternateText property of the image.

AlternateText

Sets or returns a String that contains the alternate text displayed for the image.

NullImageUrl

Sets or returns a String that contains the URL of the image to display if the data in the DataImageUrlField contains a null value.


Listing 3.11. Syntax of the ImageField Control

<asp:ImageField
  DataImageUrlField="[String]"
  DataImageUrlFormatString="[String]"
  DataImageTextField="[String]"
  DataImageTextFormatString="[String]"
  AlternateText="[String]"
  NullImageUrl="[String]"
  ApplyFormatInEditMode="[True|False]"
  HtmlEncode="[True|False]"
  Visible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

Command Columns

Earlier in the chapter, you saw that a column can be added that can issue commands to the grid. These commands can take the form of selecting rows, deleting rows, switching between display and edit mode, or a custom command. To add these commands to a grid, you use a CommandField control, the outline syntax of which is shown in Listing 3.12.

Syntax of the CommandField Control

<asp:CommandField
  ButtonType="[Button|Image|Link]"
  UpdateText="String"
  UpdateImageUrl="String"
  ShowCancelButton="[True|False]"
  CancelText="String"
  CancelImageUrl="String"
  ShowSelectButton="[True|False]"
  SelectText="String"
  SelectImageUrl="String"
  ShowEditButton="[True|False]"
  EditText="String"
  EditImageUrl="String"
  ShowInsertButton="[True|False]"
  InsertText="String"
  InsertImageUrl="String"
  NewText="String"
  NewImageUrl="String"
  ShowDeleteButton="[True|False]"
  DeleteText="String"
  DeleteImageUrl="String"
  CausesValidation="[True|False]"
  ValidationGroup="String"
  Visible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  ControlStyle-[PropertyName]="[value]"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" />

The properties in bold are specific to the CommandField control and are described in Figure, while the others are the same as those for the BoundField control.

Properties of the CommandField Control

Property/Attribute

Description

ButtonType

Sets or returns a value from the ButtonType enumeration (Button, Image, or Link) that specifies the type of controls to create in each row of this column. The default is Link.

UpdateText

Sets or returns a String value that is the caption for the button that causes an update process to occur. The default is Update.

UpdateImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Update link.

ShowCancelButton

Sets or returns a Boolean value that indicates whether a Cancel button will be displayed in this column when the row is in edit mode.

CancelText

Sets or returns a String value that is the caption for the button that cancels an update process. The default is Cancel.

CancelImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Cancel link.

ShowSelectButton

Sets or returns a Boolean value that indicates whether a Select button will be displayed in this column.

SelectText

Sets or returns a String value that is the caption for the button that causes the row to be shown in selected mode. The default is Select.

SelectImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Select link.

ShowEditButton

Sets or returns a value that indicates whether an Edit button will be displayed in this column.

EditText

Sets or returns a String value that is the caption for the button that causes the row to be shown in edit mode. The default is Edit.

EditImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Edit link.

ShowInsertButton

Sets or returns a Boolean value that indicates whether an Insert button will be displayed in this column. Inserting only has an effect in the DetailsView and FormView controls, and is not supported in the GridView control.

InsertText

Sets or returns a String value that is the caption for the button that causes the row to be shown in insert mode. The default is Insert.

InsertImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Insert link.

NewText

Sets or returns a String value that is the caption for the button that causes the row to be shown in New mode. The default is New.

NewImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text New link.

ShowDeleteButton

Sets or returns a Boolean value that indicates whether a Delete button will be displayed in this column.

DeleteText

Sets or returns a String value that is the caption for the button that deletes a row. The default is Delete.

DeleteImageUrl

Sets or returns a String that is the relative or absolute URL of the image to display in place of a text Delete link.

CausesValidation

Sets or returns a Boolean value that indicates whether the button will cause any validation controls in the page to validate their values and report any errors. The default is TRue.

ValidationGroup

Sets or returns a String that is the name of the group of validation controls that this button will be a member of. See Chapter 9 for more details about validation groups.


You can use a CommandField control to provide automatic management of data editing. For example, setting the ShowEditButton property to true will display an Edit link in the column. Clicking this link will switch the row into edit mode, which automatically shows Update and Cancel links. The former will update the underlying data with your changes, while the latter will cancel your changes. Both return the row to display mode. The ShowDeleteButton property will show a Delete link, which deletes the underlying row with no user confirmation. Confirmation and events will be covered in the Using Events section later in the chapter.

Template Columns

If the column types presented here do not give enough control over the layout of your data, you can use templated columns, which work in much the same way as templates work on controls such as the DataList or DataGrid. You specify the output in one or more templates, and the control selects the appropriate template depending upon the status of the grid. Listing 3.13 shows the outline syntax for a TemplateField control.

Syntax of the TemplateField Control

<asp:TemplateField
  ApplyFormatInEditMode="[True|False]"
  HtmlEncode="[True|False]"
  Visible="[True|False]"
  SortExpression="String"
  ShowHeader="[True|False]"
  HeaderText="String"
  AccessibleHeaderText="String"
  HeaderStyle-[PropertyName]="[value]"
  HeaderImageUrl="String"
  ItemStyle-[PropertyName]="[value]"
  FooterText="String"
  FooterStyle-[PropertyName]="[value]" >

    <HeaderTemplate>...</HeaderTemplate>
    <ItemTemplate>...</ItemTemplate>
    <AlternatingItemTemplate>...</ AlternatingItemTemplate>
    <EditItemTemplate>...</EditItemTemplate>
    <FooterTemplate>...</FooterTemplate>

<asp:TemplateField>

All the attributes of the control are the same as those listed for the BoundField control in Figure. The five kinds of templates that you can specify, highlighted in Listing 3.13, are documented in Figure.

Templates of the TemplateField Control

Template

Description

HeaderTemplate

The markup, text, controls, and other content required to generate the entire content for the header of this column of the grid.

ItemTemplate

The markup, text, controls, and other content required to generate the entire content for this column in data-bound rows within the grid.

AlternatingItemTemplate

The markup, text, controls, and other content required to generate the entire content for this column in alternating data-bound rows within the grid.

EditItemTemplate

The markup, text, controls, and other content required to generate the entire content for this column in the row within the grid that is in edit mode.

FooterTemplate

The markup, text, controls, and other content required to generate the entire content for the footer of this column of the grid.


When using template columns, you have to provide the binding directly, and for this you would use the Eval or Bind methods. The difference between these methods is that Eval provides read-only binding, while Bind provides read-write binding, and you'd generally use these in different templates. For example, consider Listing 3.14, where an ItemTemplate is used to display the price of a product, and the EditItemTemplate shows a TextBox, but also has a RequiredFieldValidator to ensure that a value is entered for the price.

Two-Way Binding in a Template

<asp:TemplateField HeaderText="Price"  SortExpression="UnitPrice"
  ItemStyle-Font-Bold="True">
  <ItemTemplate>
    <asp:Label runat="server"
      Text='<%# Eval("UnitPrice", "${0:F2}") %>' />
  </ItemTemplate>
  <EditItemTemplate>
    <asp:TextBox ID="UnitPrice" runat="server"
      Text='<%#Bind("UnitPrice")%>' />
    <asp:RequiredFieldValidator ID="rfv1" runat="server"
      ControlToValidate="UnitPrice"
      Text="You must enter the price" />
  </EditItemTemplate>
</asp:TemplateField>

This technique is very useful when you want to use the data update features of the data source and grid controls, but also need custom content such as validation or drop-down lists when the user is editing data.

The use of Eval is a shortcut to the old syntax of DataBinder.Eval. Bind is new in version 2.0.


Styling Columns

You can style columns in a number of ways, either using properties on the columns themselves, or by setting general column properties in the grid, which can be done in two ways. The first way is to set the properties on the GridView declaration, like this:

<asp:GridView ID="grid1" runat="server" DataSourceID="ds1"
  RowStyle-BackColor="Aqua" HeaderStyle-Font-Bold="True"

Alternatively, you can set the styling as separate elements, like this:

<asp:GridView ID="grid1" runat="server" DataSourceID="ds1">
  <HeaderStyle Font-Bold="true" Font-Names="Verdana" />
  <RowStyle Font-Names="Verdana" />
</asp:GridView>

There is no practical difference between the two methods, although the latter style is easier to read and keeps the styling separate from the rest of the grid declaration. Styles can also be set on columns, like this:

<asp:HyperLinkField DataTextField="ProductName"
  ItemStyle-Font-Bold="True" ItemStyle-BackColor="Yellow" />

As well as using the individual style elements, you can use CSS to style elements by using the CssClass property.

<asp:HyperLinkField DataTextField="ProductName"

  CssClass="GridLink" />

The following eight style elements are available:

  • AlternatingRowStyle, for alternating rows (RowStyle handles the others)

  • EditRowStyle, for rows in edit mode

  • EmptyDataRowStyle, for the row shown when there is no data to display

  • FooterStyle, for the footer row

  • HeaderStyle, for the header row

  • PagerStyle, for the page row

  • RowStyle, for all rows, unless AlternatingRowStyle is also set

  • SelectedRowStyle, for rows selected by a select command

Styles used on individual columns override any styles set at the grid level.

Custom GridView Commands

You are not limited to using a CommandField to issue commands, because any button control (anything that causes a postback) can be set to emulate the standard commands. Each submit-style button has two properties, CommandName and CommandArgument, which can be set to a specific command. When an appropriately set button is clicked within the context of a grid row, the command is executed. For example, consider the following:

<asp:LinkButton id="LinkButton1" runat="server"
  CommandName="Edit" Text="Edit" />

If this is placed in a column, then clicking the link will execute the Edit command, switching the row into edit mode, exactly as it would be done through a standard edit Command button. You can set the CommandName property to any of the following: Insert, Cancel, Delete, New, or Select.

Putting it All TogetherA Customized GridView Control

There is no limit to the way you can combine columns, and you can even leave the auto-generation of columns on and define columns within the <Columns> section. In this case, any columns you explicitly define are placed at the start of the grid, while automatic columns are placed afterwards. It's generally better to explicitly name the columns, because you then have control over how they appear. Figure shows a grid with a variety of column types and formats.

11. A GridView with a mixture of column types


Definition of this grid is as shown in Listing 3.15. Auto-generation of columns is disabled, and sorting and paging are enabled, with a style set for the header and each row.

Although not the best looking grid, you can see that the column types and styling give you a great deal of flexibility in the look and feel of grids. You can see that although editing is possible, when you come to edit more than one or two columns, the GridView could have limitations. For example, adding validation is possible, but validation errors might not fit within the grid cells. Or what if you have a column that accepts a large amount of texta product description perhapswhere a cell within a grid would provide a restrictive way of both viewing and editing the data? A better editing solution, or for display of single rows of data, is to use either a DetailsView or FormView control.

The GridView Definition

<asp:GridView ID="grid1" runat="server" DataSourceID="ds1"
  DataKeyNames="ProductID"
  AutoGenerateColumns="False"
  AllowSorting="True" AllowPaging="True" PageSize="5">
  <HeaderStyle Font-Bold="True" Font-Names="Verdana" />
  <RowStyle Font-Names="Verdana" />
  <Columns>
    <asp:ButtonField ButtonType="Button" DataTextField="ProductID"
      SortExpression="ProductID" HeaderText="ID" />

    <asp:HyperLinkField DataTextField="ProductName"
      DataNavigateUrlFields="ProductID,ProductName"
      DataNavigateUrlFormatString="http://www.site-that-shows-more-
info.com/products?product={0}&name={1}"
      SortExpression="ProductName" HeaderText="Product"
      ItemStyle-Font-Bold="True" ItemStyle-BackColor="Yellow" />

    <asp:BoundField DataField="QuantityPerUnit"
      HeaderText="Packaging"  />

    <asp:CheckBoxField DataField="Discontinued" HeaderText="N/A" >

    <asp:TemplateField HeaderText="Price"
      SortExpression="UnitPrice" ItemStyle-Font-Bold="True">
      <ItemTemplate>
        <asp:Label runat="server"
          Text='<%# Eval("UnitPrice", "${0:F2}") %>62;' />
      </ItemTemplate>
      <AlternatingItemTemplate>
        <asp:Label runat="server" ForeColor="DarkGray"
          Text='<%# Eval("UnitPrice", "${0:F2}") %>' />;
      </AlternatingItemTemplate>
      <EditItemTemplate>
        <asp:TextBox ID="UnitPrice" runat="server"
          Text='<%#Bind("UnitPrice")%>' />
        <asp:RequiredFieldValidator ID="rfv1" runat="server"
          ControlToValidate="UnitPrice"
          Text="You must enter the price" />
      </EditItemTemplate>
    </asp:TemplateField>

    <asp:CommandField ButtonType="Image" ShowCancelButton="True"
      ShowEditButton="True" ShowDeleteButton="True"
      CancelImageUrl="s.gif" EditImageUrl="q.gif"
      UpdateImageUrl="i.gif" DeleteImageUrl="x.gif"
      CancelText="Cancel this update" EditText="Edit this row"
      UpdateText="Apply these changes" DeleteText="Delete this row"/>

  </Columns>
</asp:GridView>

The DetailsView Control

The DetailsView control provides a view of a single row of the data, in a form style rather than a grid style. The DetailsView can be used stand-alone, or in combination with a GridView, for showing and editing individual rows. This works well when combining the selection from a grid and a SelectParameters on a SqlDataSource control, as shown in Listing 3.16.

Using a DetailsView Control

<asp:SqlDataSource ID="SqlDataSource2" runat="server"
  ConnectionString="<%$ ConnectionStrings:NorthwindConnectString %>"
  DeleteCommand="..." InsertCommand="..." UpdateCommand="..."
  SelectCommand="SELECT * FROM Products
                 WHERE ProductID = @ProductID)">
  ...
  <SelectParameters>
    <asp:ControlParameter ControlID="GridView1"
      Name="ProductID" PropertyName="SelectedValue"
      Type="Int32" />
  </SelectParameters>
</asp:SqlDataSource>

<asp:DetailsView ID="DetailsView1" runat="server"
  DataKeyNames="ProductID" DataSourceID="SqlDataSource2">
</asp:DetailsView>

Figure shows the DetailsView displaying a row of data, with the row having been selected in a GridView.

12. Showing a single row with a DetailsView control


By default the DetailsView does not show any edit commands, but these can be added in one of two ways. The first is by properties on the control itself, like this:

<asp:DetailsView ID="DetailsView1" runat="server"
  DataKeyNames="ProductID" DataSourceID="SqlDataSource2"
  AutoGenerateInsertButton="True"
  AutoGenerateDeleteButton="True"
  AutoGenerateEditButton="True">

This would add the commands at the bottom of the control, as shown in Figure. Alternatively, a CommandField can be explicitly defined, like this:

<asp:DetailsView ID="DetailsView1" runat="server"
  DataKeyNames="ProductID" DataSourceID="SqlDataSource2">
  <Fields>
    <asp:CommandField ShowDeleteButton="True" ShowEditButton="True"
      ShowInsertButton="True" />
  </Fields>
</asp:DetailsView>

Like the GridView, the default behavior is suitable for both display and editing of data, but it does have the same limitations, such as how to display different controls to edit the data.

Defining Fields

The DetailsView automatically generates the fields based upon the underlying data. Like the GridView though, automatic generation of fields can be turned off and the fields specified directly. This is done with the AutoGenerateRows property and the Fields subelement, as shown in Listing 3.17.

Defining the Fields on a DetailsView

<Fields>
  <asp:BoundField DataField="ProductID"
    HeaderText="ProductID" InsertVisible="False"
    ReadOnly="True" SortExpression="ProductID" />
  <asp:BoundField DataField="ProductName"
    HeaderText="ProductName" SortExpression="ProductName" />
  <asp:BoundField DataField="SupplierID"
    HeaderText="SupplierID" SortExpression="SupplierID" />
  <asp:BoundField DataField="CategoryID"
    HeaderText="CategoryID" SortExpression="CategoryID" />
  <asp:BoundField DataField="QuantityPerUnit"
    HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" />
  <asp:BoundField DataField="UnitPrice"
    HeaderText="UnitPrice" SortExpression="UnitPrice" />
  <asp:BoundField DataField="UnitsInStock"
    HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
  <asp:BoundField DataField="UnitsOnOrder"
    HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
  <asp:BoundField DataField="ReorderLevel"
    HeaderText="ReorderLevel" SortExpression="ReorderLevel" />
  <asp:CheckBoxField DataField="Discontinued"
    HeaderText="Discontinued" SortExpression="Discontinued" />
  <asp:CommandField ShowDeleteButton="True"
    ShowEditButton="True" ShowInsertButton="True" />
</Fields>

You can see that these are the same fields as used in the GridView, so you can use TemplateField controls to provide customization, such as displaying drop-down lists for supplier and category when editing data, as shown Listing 3.18 with the supplier.

Using TemplateField Controls

<asp:TemplateField HeaderText="Supplier">
  <ItemTemplate>
    <%#Eval("CompanyName") %>
  </ItemTemplate>
  <EditItemTemplate>
    <asp:SqlDataSource ID="Sds1" runat="server"
     ConnectionString="<%$ConnectionStrings:NorthwindConnectString%>"
      SelectCommand="SELECT SupplierID, CompanyName
                     FROM Suppliers ORDER BY CompanyName" />
    <asp:DropDownList ID="SupplierID" runat="server"
      DataSourceId="Sds1"
      DataValueField="SupplierID" DataTextField="CompanyName"
      SelectedValue='<%#Bind("SupplierID")%>' />
  </EditItemTemplate>
</asp:TemplateField>

You can see that the ItemTemplate simply displays the CompanyName, while the EditItemTemplate contains a SqlDataSource and a Drop-DownList. The data source fetches the ID and name of all suppliers, and the list binds to this data, as seen in Figure. The DataValueField holds the ID, while the DataTextField holds the display data. The key item here is the SelectedValue, which is set to a data-binding expression, using Bind to provide two-way binding to the SupplierID column. Because SelectedValue is used, whatever SupplierID the underlying row has is displayed as the currently selected item in the list, and because Bind is used, when the Update link is clicked, that new SupplierID is pushed back to the database through the data source control.

13. TemplateColumns with DropDownLists


The DetailsView can be further customized with styling, in a similar way to the GridView. The DetailsView supports the following style elements:

  • AlternatingRowStyle, for alternating rows (RowStyle handles the others)

  • CommandRowStyle, for the row holding the commands (Edit, New, etc.)

  • EditRowStyle, for rows in edit mode

  • EmptyDataRowStyle, for the row shown when there is no data to display

  • FieldHeaderStyle, for the row headers

  • FooterStyle, for the footer row

  • HeaderStyle, for the header row

  • InsertRowStyle, for the row shown when in insert mode

  • PagerStyle, for the page row

  • RowStyle, for all rows, unless AlternatingRowStyle is also set

There are also other properties, such as GridLines, which sets the display borders, so you can remove the grid-like look this control has.

Using a Stand-Alone DetailsView

The DetailsView doesn't have to be used in conjunction with another control, displaying details for a selection, but can be used stand-alone. While it still only displays one row at a time, it can step through rows in a set of data, as shown in Figure, where three records have been stepped through. The navigation buttons are intelligent, so they only show when required; for the first record, only the Next and Last buttons are visible, while for the last record on, the First and Previous buttons are visible.

14. The DetailsView in standalone mode


Custom DetailsView Commands

Like the GridView, any button can emulate the standard button commands by use of the CommandName and CommandArgument properties. For the standard commands, the CommandName would be set to one of: Insert, Cancel, Delete, New, or Select. To emulate the paging buttons, you set the CommandName to Page and the CommandArgument to one of First, Last, Prev, or Next. For example:

<asp:LinkButton id="LinkButton1" runat="server"
  CommandName="Page" CommandArgument="First"
  Text="First" />

The FormView Control

If more flexibility is required than the DetailsView provides, then a FormView can be used. This is very similar in action to a DetailsView, displaying a single row at a time, but it provides no default user interface; you have to provide the entire interface via templates. Most of the properties and usage of the FormView are the same as for the DetailsView, but conceptually it differs in one major way. When using custom columns on the DetailsView, you define the fields, and then within the fields, you define the templates. With the FormView, because there is no default interface, you define the templates, and then within the templates, you put all of the content to be displayed when that template is visible. For example, consider Figure, which shows three states of a FormView.

15. The FormView control in normal, insert, and edit modes


The FormView declaration is shown in Listing 3.19.

The FormView Declaration

<asp:FormView id="FormView1" DataSourceID="dvs1" runat="server"
  DataKeyNames="ShipperID" AllowPaging="True"
  PagerSettings-Mode="Numeric">

Listing 3.20 shows the ItemTemplate, and you can see that the entire interface is detailed, including a table for layout, standard server controls using read-only binding, and LinkButton controls for the commands, which allow rows to be edited, deleted, and added.

The FormView ItemTemplate

<ItemTemplate>
  <table border="0" cellpadding="5">
  <tr>
    <td>
      <asp:Image ID="Image1" runat="server"
        Width="100" Height="123"
        ImageUrl='<%# Eval("ShipperID", "{0}.gif") %>'
        AlternateText='<%# Eval("CompanyName", "{0} Logo") %>' />
    </td>
    <td>
      <b><%# Eval("CompanyName") %></b><p />
      <%# Eval("Phone") %><p />
      <asp:LinkButton id="btnEdit" runat="server"
        CommandName="Edit" Text="Edit Details" /><br />
      <asp:LinkButton id="btnDelete" runat="server"
        CommandName="Delete" Text="Delete Shipper" /><br />
      <asp:LinkButton id="btnInsert" runat="server"
        CommandName="New" Text="Add New Shipper" />
    </td>
  </tr>
  </table>
</ItemTemplate>

Listing 3.21 shows the EditItemTemplate, with both read-only and read-write binding. The read-only binding is used for the ShipperID, the primary key column of the table, which cannot be edited. The CompanyName and Phone columns use Bind to allow the user-entered value to be pushed back to the database. Because this template is shown when editing data, the buttons have their commands set to Update and Cancelthe two actions that can be performed on a row in edit mode.

The FormView EditItemTemplate

<EditItemTemplate>
  <table border="0" cellpadding="5">
    <tr>
      <td align="right">ShipperID:</td>
      <td><%# Eval("ShipperID") %></td>
    </tr>
    <tr>
      <td align="right">Company Name:</td>
      <td>
        <asp:TextBox id="txtEditName" runat="server"
             Text='<%# Bind("CompanyName") %>' />
      </td>
    </tr>
    <tr>
      <td align="right">Phone:</td>
      <td>
        <asp:TextBox id="txtEditPhone" runat="server"
          Text='<%# Bind("Phone") %>' />
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <asp:LinkButton id="btnUpdate" CommandName="Update"
          Text="Update" runat="server" />
        <asp:LinkButton id="btnCancel" CommandName="Cancel"
          Text="Cancel" runat="server" />
      </td>
    </tr>
  </table>
</EditItemTemplate>

Listing 3.22 shows the InsertItemTemplate, which uses Bind for read-write binding of the ShipperID and Phone; even though this is a new row, Bind is still used. Because this is a new row, the commands are set to Add and Cancel; Add will add the new row, calling the InsertMethod, while Cancel will cancel the insertion and return the row to display mode.

The FormView InsertItemTemplate

<InsertItemTemplate>
  <table border="0" cellpadding="5">
    <tr>
      <td align="right">ShipperID:</td>
      <td>
        <asp:TextBox id="txtInsertID" runat="server"
          Text='<%# Bind("ShipperID") %>' />
      </td>
    </tr>
    <tr>
      <td align="right">Company Name:</td>
      <td>
        <asp:TextBox id="txtInsertName" runat="server"
          Text='<%# Bind("CompanyName") %>' />
      </td>
    </tr>
    <tr>
      <td align="right">Phone:</td>
      <td>
        <asp:TextBox id="txtInsertPhone" runat="server"
          Text='<%# Bind("Phone") %>' />
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <asp:LinkButton id="btnAdd" CommandName="Insert"
          Text="Add" runat="server" />
        <asp:LinkButton id="btnAbandon" CommandName="Cancel"
          Text="Cancel" runat="server" />
      </td>
    </tr>
  </table>
</InsertItemTemplate>

You can see that even though there is more source, there is still no requirement for code to provide data updates. The techniques for the DetailsView and FormView are very similar, and the whole use of commands is common to all of these data controls. The declarative nature of these controls makes them easy to use, but there are still occasions when code is required. The first is if you want to avoid the two-tier system of the SqlDataSource, such as using a separate data layer, which is covered in Chapter 4, and the second is when you require some advanced features of the data source and grid controls, which is covered in Chapter 5.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows