To create a custom field, you can inherit a new class from any of the existing fields or any of the following base classes:... In this section, you learn how to create a long text field,
Trang 1.categories h1
{
font:bold 16px Arial, Sans-Serif;
}
.movies
{
margin-left:20px;
margin-bottom:10px;
width:100%;
}
</style>
<title>Nested Master/Detail</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovieCategories”
OnRowDataBound=”grdMovieCategories_RowDataBound”
AutoGenerateColumns=”false”
CssClass=”categories”
ShowHeader=”false”
GridLines=”none”
Runat=”server”>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<h1><%# Eval(“Name”) %></h1>
<asp:GridView
id=”grdMovies”
DataSourceId=”srcMovies”
CssClass=”movies”
GridLines=”none”
Runat=”server” />
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Title,Director FROM Movies WHERE CategoryId=@CategoryId”
Runat=”server”>
<SelectParameters>
<asp:Parameter Name=”CategoryId” />
</SelectParameters>
Trang 2</asp:SqlDataSource>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource
id=”srcMovieCategories”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Id,Name FROM MovieCategories”
Runat=”server” />
</div>
</form>
</body>
</html>
The grdMovieCategories_RowDataBound() method handles the RowDataBound event This
event handler grabs the movie category ID from the current row’s DataItem property
Next, it retrieves the SqlDataSource control contained in the grdMovieCategories
TemplateField Finally, it assigns the movie category ID to a parameter contained in the
SqlDataSource control’s SelectParameters collection
NOTE
You must use the FindControl() method to get the SqlDataSource control from the
TemplateField The templates in a TemplateField each create their own naming
con-tainers to prevent naming collisions The FindControl() method enables you to
search a naming container for a control with a matching ID
Extending the GridView Control
Like any other control in the ASP.NET Framework, if you don’t like any aspect of the
GridView control, you always have the option of extending the control In this section,
you learn how to extend the GridView control with custom fields
To create a custom field, you can inherit a new class from any of the existing fields or any
of the following base classes:
Trang 3DataControlField—The base class for all fields
ButtonFieldBase—The base class for all button fields, such as the ButtonField and
CommandField
In this section, you learn how to create a long text field, a delete button field, and a
vali-dated field
Creating a LongTextField
None of the existing GridView fields do a good job of handling large amounts of text You
can fix this problem by creating a custom field, named the LongTextField, which you can
use to display the value of text columns regardless of the length of the text
In normal display mode, LongTextField displays the text in a scrolling <div> tag In edit
display mode, the text appears in a multiline TextBox control (see Figure 11.23)
FIGURE 11.23 Displaying a long text field
To create a custom field, a new class must be inherited from the base BoundField control
The custom LongTextField is contained in Listing 11.31
Trang 4LISTING 11.31 LongTextField.cs
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace myControls
{
/// <summary>
/// Enables you to display a long text field
/// </summary>
public class LongTextField : BoundField
{
private Unit _width = new Unit(“250px”);
private Unit _height = new Unit(“60px”);
/// <summary>
/// The Width of the field
/// </summary>
public Unit Width
{
get { return _width; }
set { _width = value; }
}
/// <summary>
/// The Height of the field
/// </summary>
public Unit Height
{
get { return _height; }
set { _height = value; }
}
/// <summary>
/// Builds the contents of the field
/// </summary>
protected override void InitializeDataCell(DataControlFieldCell cell,
DataControlRowState rowState)
{
// If not editing, show in scrolling div
if ((rowState & DataControlRowState.Edit) == 0)
{
HtmlGenericControl div = new HtmlGenericControl(“div”);
div.Attributes[“class”] = “longTextField”;
Trang 5div.Style[HtmlTextWriterStyle.Width] = _width.ToString();
div.Style[HtmlTextWriterStyle.Height] = _height.ToString();
div.Style[HtmlTextWriterStyle.Overflow] = “auto”;
div.DataBinding += new EventHandler(div_DataBinding);
cell.Controls.Add(div);
}
else
{
TextBox txtEdit = new TextBox();
txtEdit.TextMode = TextBoxMode.MultiLine;
txtEdit.Width = _width;
txtEdit.Height = _height;
txtEdit.DataBinding += new EventHandler(txtEdit_DataBinding);
cell.Controls.Add(txtEdit);
}
}
/// <summary>
/// Called when databound in display mode
/// </summary>
void div_DataBinding(object s, EventArgs e)
{
HtmlGenericControl div = (HtmlGenericControl)s;
// Get the field value
Object value = this.GetValue(div.NamingContainer);
// Assign the formatted value
div.InnerText = this.FormatDataValue(value, this.HtmlEncode);
}
/// <summary>
/// Called when databound in edit mode
/// </summary>
void txtEdit_DataBinding(object s, EventArgs e)
{
TextBox txtEdit = (TextBox)s;
// Get the field value
Object value = this.GetValue(txtEdit.NamingContainer);
// Assign the formatted value
Trang 6txtEdit.Text = this.FormatDataValue(value, this.HtmlEncode);
}
}
}
In Listing 11.31, the InitializeDataCell() method is overridden This method is
respon-sible for creating all the controls that the custom field contains
First, a check is made to determine whether the field is rendered when the row is selected
for editing A bitwise comparison must be performed with the rowState parameter because
the rowState parameter can contain combinations of the values Alternate, Normal,
Selected, and Edit (for example, RowState can be both Alternate and Edit)
When the row is not in edit mode, a <div> tag is created to contain the text
HtmlGenericControl represents the <div> tag When GridView is bound to its data
source, the <div> tags get the value of its innerText property from the
div_DataBinding() method
When the row is selected for editing, a multiline TextBox control is created When
GridView is bound to its data source, the TextBox control’s Text property gets its value
from the txtEdit_DataBinding() method
You can experiment with LongTextField with the page in Listing 11.32 This page uses
LongTextField to display the value of the Movie Description column
LISTING 11.32 ShowLongTextField.aspx
<%@ Page Language=”C#” %>
<%@ Register TagPrefix=”custom” Namespace=”myControls” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<style type=”text/css”>
.grid td, grid th
{
padding:5px;
}
</style>
<title>Show LongTextField</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView
Trang 7id=”grdMovies”
CssClass=”grid”
DataSourceID=”srcMovies”
DataKeyNames=”Id”
AutoGenerateColumns=”false”
AutoGenerateEditButton=”true”
Runat=”server”>
<Columns>
<asp:BoundField
DataField=”Title”
HeaderText=”Movie Title” />
<asp:BoundField
DataField=”Director”
HeaderText=”Movie Director” />
<custom:LongTextField
DataField=”Description”
Width=”300px”
Height=”60px”
HeaderText=”Movie Description” />
</Columns>
</asp:GridView>
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Id, Title, Director, Description
FROM Movies”
UpdateCommand=”UPDATE Movies SET
Title=@Title,Director=@Director,Description=
WHERE Id=@Id”
Runat=”server” />
</div>
</form>
</body>
</html>
Creating a DeleteButtonField
I don’t like the Delete button rendered by the GridView control’s CommandField The
problem is that it does not provide you with any warning before you delete a record In
this section, we fix this problem by creating a Delete button that displays a client-side
confirmation dialog box (see Figure 11.24)
Trang 8DeleteButtonField inherits from the ButtonField class The code for the custom field is
contained in Listing 11.33
LISTING 11.33 DeleteButtonField.cs
using System;
using System.Web.UI.WebControls;
namespace myControls
{
/// <summary>
/// Displays a confirmation before deleting a record
/// </summary>
public class DeleteButtonField : ButtonField
{
private string _confirmText = “Delete this record?”;
public string ConfirmText
{
get { return _confirmText; }
set { _confirmText = value; }
}
FIGURE 11.24 Displaying a confirmation dialog box
Trang 9public DeleteButtonField()
{
this.CommandName = “Delete”;
this.Text = “Delete”;
}
public override void InitializeCell(DataControlFieldCell cell,
DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
base.InitializeCell(cell, cellType, rowState, rowIndex);
if (cellType == DataControlCellType.DataCell)
{
WebControl button = (WebControl)cell.Controls[0];
button.Attributes[“onclick”] = String.Format(“return
➥confirm(‘{0}’);”, _confirmText);
}
}
}
}
Most of the work in Listing 11.33 is handled by the base ButtonField class The
InitializeCell() method is overridden so that the button can be grabbed The button is
added to the cell by the base ButtonField’s InitializeCell() method
To create the confirmation dialog box, an onclick attribute is added to the button If the
JavaScript confirm statement returns false, the button click is canceled
You can test the DeleteButtonField with the page in Listing 11.34 This page enables you
to delete records from the Movies database table
LISTING 11.34 ShowDeleteButtonField.aspx
<%@ Page Language=”C#” %>
<%@ Register TagPrefix=”custom” Namespace=”myControls” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<style type=”text/css”>
.grid td, grid th
{
padding:5px;
}
</style>
Trang 10<title>Show DeleteButtonField</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView
id=”grdMovies”
CssClass=”grid”
DataSourceID=”srcMovies”
DataKeyNames=”Id”
AutoGenerateColumns=”false”
Runat=”server”>
<Columns>
<custom:DeleteButtonField
ConfirmText=”Are you sure that you want to delete this record?” />
<asp:BoundField
DataField=”Title”
HeaderText=”Movie Title” />
<asp:BoundField
DataField=”Director”
HeaderText=”Movie Director” />
</Columns>
</asp:GridView>
<asp:SqlDataSource
id=”srcMovies”
ConnectionString=”<%$ ConnectionStrings:Movies %>”
SelectCommand=”SELECT Id, Title, Director FROM Movies”
DeleteCommand=”DELETE Movies WHERE Id=@Id”
Runat=”server” />
</div>
</form>
</body>
</html>
Creating a ValidatedField
In this final section, we create a ValidatedField custom field, which automatically
vali-dates the data that a user enters into GridView when editing a record ValidatedField
uses RequiredFieldValidator to check whether a user has entered a value, and
CompareValidator to check whether the value is the correct data type (see Figure 11.25)