Listing 7-35: Adding an UpdateCommand to a SqlDataSource control Notice that the UpdateCommand includes a number of placeholders such as@CompanyName,@Country, @Region, and@CustomerID..
Trang 1your existing SqlDataSource control by adding anUpdateCommandattribute This tells the data source
control what SQL it should execute when it is requested to perform an update Listing 7-35 shows the
code to add theUpdateCommandattribute
Listing 7-35: Adding an UpdateCommand to a SqlDataSource control
<asp:SqlDataSource ID="SqlDataSource1" Runat="server"
SelectCommand="SELECT * FROM [Customers]"
ConnectionString="<%$ ConnectionStrings:AppConnectionString1 %>"
DataSourceMode="DataSet"
UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName,
[ContactName] = @ContactName, [ContactTitle] = @ContactTitle,
[Address] = @Address, [City] = @City, [Region] = @Region,
[PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone,
[Fax] = @Fax WHERE [CustomerID] = @original_CustomerID">
Notice that the UpdateCommand includes a number of placeholders such as@CompanyName,@Country,
@Region, and@CustomerID These are placeholders for the corresponding information that will come
from the selected row in GridView In order to use the parameters, you must define them using the
UpdateParameterselement of the SqlDataSource control TheUpdateParameterselement, shown in
Listing 7-36, works much like theSelectParameterselement discussed earlier in the chapter
Listing 7-36: Adding UpdateParameters to the SqlDataSource control
<asp:SqlDataSource ID="SqlDataSource1" Runat="server"
SelectCommand="SELECT * FROM [Customers]"
ConnectionString="<%$ ConnectionStrings:AppConnectionString1 %>"
DataSourceMode="DataSet"
UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName,
[ContactName] = @ContactName, [ContactTitle] = @ContactTitle,
[Address] = @Address, [City] = @City, [Region] = @Region,
[PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone,
[Fax] = @Fax WHERE [CustomerID] = @original_CustomerID">
<UpdateParameters>
<asp:Parameter Type="String" Name="CompanyName"></asp:Parameter>
<asp:Parameter Type="String" Name="ContactName"></asp:Parameter>
<asp:Parameter Type="String" Name="ContactTitle"></asp:Parameter>
<asp:Parameter Type="String" Name="Address"></asp:Parameter>
<asp:Parameter Type="String" Name="City"></asp:Parameter>
<asp:Parameter Type="String" Name="Region"></asp:Parameter>
<asp:Parameter Type="String" Name="PostalCode"></asp:Parameter>
<asp:Parameter Type="String" Name="Country"></asp:Parameter>
<asp:Parameter Type="String" Name="Phone"></asp:Parameter>
<asp:Parameter Type="String" Name="Fax"></asp:Parameter>
<asp:Parameter Type="String" Name="CustomerID"></asp:Parameter>
</UpdateParameters>
</asp:SqlDataSource>
Within theUpdateParameterselement, each named parameter is defined using the<asp:Parameter>
element This element uses two attributes that define the name and the data type of the parameter In
this case, all the parameters are of typeString Remember that you can also use any of the parameter
types mentioned earlier in the chapter, such as theControlParameterorQueryStringParameterin the UpdateParameterselement
Trang 2Next, you give the grid a column it can use to trigger editing of a data row You can do this in several
ways First, you can use the GridView’sAutoGenerateEditButtonproperty When set toTrue, this
property tells the grid to add to itself aButtonFieldcolumn with an edit button for each data row
Listing 7-37 shows how to add theAutoGenerateEditButtonattribute to the GridView control
Listing 7-37: Adding the AutoGenerateEditButton attribute to a SqlDataSource control
<asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1"
DataKeyNames="CustomerID" AutoGenerateColumns="False"
AllowSorting="True" AllowPaging="True"
AutoGenerateEditButton="true">
The GridView control also includesAutoGenerateSelectButtonandAutoGenerateDeleteButton
prop-erties, which allow you to easily add row selection and row deletion capabilities to the grid
A second way to add an edit button is to add aCommandFieldcolumn This is shown in Listing 7-38
Listing 7-38: Adding edit functionality using a CommandField
<asp:CommandField ShowHeader="True" HeaderText="Command"
ShowEditButton="True"></asp:CommandField>
Notice that you add theShowEditButtonproperty to theCommandFieldto indicate that you want to
display the edit command in this column You can control how the command is displayed in the grid
using theButtonTypeproperty, which allows you to display the command as a link, a button, or even an
image Figure 7-25 shows what the grid looks like after adding theCommandFieldwith theeditcommand
displayed
Now if you browse to your Web page, you see that a new edit column has been added Clicking the Edit
link allows the user to edit the contents of that particular data row
TheCommandFieldelement also has attributes that allow you to control exactly what is shown in the
column You can dictate whether the column displays commands such asCancel,Delete,Edit,Insert,
andSelect
With the EditCommandFieldenabled, you still have one more property to set in order to enable the grid
to perform updates You tell the grid which columns are in the table’s primary key You can accomplish
this by using theDataKeyNamesproperty, as illustrated in Listing 7-39
Listing 7-39: Adding the DataKeyNames to the GridView control
<asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1"
DataKeyNames="CustomerID" AutoGenerateColumns="False"
AllowSorting="True" AllowPaging="True"
AutoGenerateEditButton="true">
You can specify more than one column in the primary key by setting the property to a
comma-delimited list
Notice that when you add the edit capabilities to the grid, by default it allows all displayed columns to
be edited You probably won’t always want this to be the case You can control which columns the grid
Trang 3allows to be edited by adding theReadOnlyproperty to the columns that you do not want users to edit Listing 7-40 shows how you can add theReadOnlyproperty to the ID column
Figure 7-25
Listing 7-40: Adding the ReadOnly property to a BoundField
<asp:BoundField ReadOnly="True" HeaderText="CustomerID" DataField="CustomerID"
SortExpression="CustomerID" Visible="False"></asp:BoundField>
Now if you browse to the Web page again and click the Edit button, you should see that the ID column
is not editable This is shown in Figure 7-26
Handling Errors When Updating Data
As much as you try to prevent them, errors happen when you save data If you allow your users to
update data in your GridView control, you should implement a bit of error handling to make sure errors
do not bubble up to the user
To check for errors when updating data through the GridView, you can use theRowUpdatedevent
Listing 7-41 shows how to check for errors after a user has attempted to update data In this scenario,
if an error does occur, you simply display a message to the user in a Label
Trang 4Figure 7-26
Listing 7-41: Checking for Update errors using the RowUpdated event
VB
<script runat="server">
Protected Sub GridView1_RowUpdated(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs)
If e.Exception IsNot Nothing Then Me.lblErrorMessage.Text = e.Exception.Message End If
End Sub
</script>
C#
<script runat="server">
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
if (e.Exception != null)
Trang 5{ this.lblErrorMessage.Text = e.Exception.Message;
} }
</script>
Using the TemplateField’s EditItemTemplate
Earlier in the chapter, you were introduced to the TemplateField and various other available templates One of those templates is the EditItemTemplate, which the grid uses to display the TemplateField column for a row that has entered edit mode Although the standard BoundField allows users to edit their data only in text boxes, the TemplateField’s EditItemTemplate enables you to completely customize the data editing experience of the user For instance, the user would probably have a better editing experience if the Region column were presented as a DropDownList control during edit mode, rather than as a simple text box
To do this, you simply change the Region column from a BoundField to a TemplateField and add an
ItemTemplate and an EditItemTemplate In the EditItemTemplate, you can add a DropDownList control and provide the proper data-binding information so that the control is bound to a unique list of Regions Listing 7-42 shows how you can add the ItemTemplate and EditItemTemplate to the GridView
Listing 7-42: Adding the ItemTemplate and EditItemTemplate to the GridView
<asp:TemplateField HeaderText="Country">
<ItemTemplate><%# Eval("Country") %></ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="SqlDataSource2"
DataTextField="Country" DataValueField="Country">
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT DISTINCT [Country] FROM [Customers]">
</asp:SqlDataSource>
</EditItemTemplate>
</asp:TemplateField>
Notice that you use a simple Eval data-binding expression in the ItemTemplate to display the value of the column in the row’s default display mode In the EditItemTemplate, you simply include a DropDownList control and a SqlDataSource control for the drop-down list to bind to
To select the current Country value in the DropDownList control, you use theRowDataBoundevent
Listing 7-43 shows how this is done
Listing 7-43: Using RowDataBound
VB
Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
’Check for a row in edit mode
If ((e.Row.RowState = DataControlRowState.Edit) Or _
Continued
Trang 6(e.Row.RowState = (DataControlRowState.Alternate Or _ DataControlRowState.Edit))) Then
Dim drv As System.Data.DataRowView = _ CType(e.Row.DataItem, System.Data.DataRowView) Dim ddl As DropDownList = _
CType(e.Row.Cells(8).FindControl("DropDownList1"), DropDownList) Dim li As ListItem = ddl.Items.FindByValue(drv("Country").ToString()) li.Selected = True
End If
End Sub
C#
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Check for a row in edit mode
if ( (e.Row.RowState == DataControlRowState.Edit) ||
(e.Row.RowState == (DataControlRowState.Alternate |
DataControlRowState.Edit)) ) {
System.Data.DataRowView drv = (System.Data.DataRowView)e.Row.DataItem;
DropDownList ddl = (DropDownList)e.Row.Cells[8].FindControl("DropDownList1");
ListItem li = ddl.Items.FindByValue(drv["Country"].ToString());
li.Selected = true;
}
}
As shown in the listing, to set the appropriate DropDownList value, first check that the currently bound
GridViewRow is in an edit state by using theRowStateproperty TheRowStateproperty is a bitwise
combination of DataControlRowState values The following table shows you the possible states for a
GridViewRow
RowState Description
Alternate Indicates that this row is an alternate row
Insert Indicates the row is a new row, and is currently in insert mode
Normal Indicates the row is currently in a normal state
Selected Indicates the row is currently the selected row in the GridView
Note that in order to determine the current RowState correctly in the previous listing, you must make
multiple comparisons against theRowStateproperty The RowState can be in multiple states at once —
for example, alternate and edit Therefore, you need to use a bitwise comparison to properly
deter-mine if the GridViewRow is in an edit state After the row is deterdeter-mined to be in an edit state, locate
the DropDownList control in the proper GridViewRow cell by using theFindControlmethod This
Trang 7method allows you to locate a server control by name After you find the DropDownList control, locate the appropriate DropDownlist ListItem and set itsSelectedproperty toTrue
You also need to use a GridView event to add the value of the DropDownList control back into the
GridView after the user updates the row For this, you can use theRowUpdatingevent as shown in
Listing 7-44
Listing 7-44: Using RowUpdating
VB
Protected Sub GridView1_RowUpdating(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs)
Dim gvr As GridViewRow = Me.GridView1.Rows(Me.GridView1.EditIndex)
Dim ddl As DropDownList = _
CType(gvr.Cells(8).FindControl("DropDownList1"), DropDownList) e.NewValues("Country") = ddl.SelectedValue
End Sub
C#
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow gvr = this.GridView1.Rows[this.GridView1.EditIndex];
DropDownList ddl = (DropDownList)gvr.Cells[8].FindControl("DropDownList1");
e.NewValues["Country"] = ddl.SelectedValue;
}
In this event, you determine GridViewRow that is currently being edited using theEditIndex This
property contains the index of the GridViewRow that is currently in an edit state After you find the
row, locate the DropDownList control in the proper row cell using theFindControlmethod, as in the
previous listing After you find the DropDownList control, simply add theSelectedValueof that control
to the GridView controlsNewValuescollection
Deleting GridView Data
Deleting data from the table produced by the GridView is even easier than editing data Just a few addi-tions to the code enable you to delete an entire row of data from the table Much like with the Edit buttons you added earlier, you can easily add a Delete button to the grid by setting the
AutoGenerateDelete-Buttonproperty toTrue This is shown in Listing 7-45
Listing 7-45: Adding a delete link to the GridView
<asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1"
DataKeyNames="CustomerID" AutoGenerateColumns="False"
AllowSorting="True" AllowPaging="True"
AutoGenerateEditButton="true" AutoGenerateDeleteButton="true">
The addition of theAutoGenerateDeleteButtonattribute to the GridView is the only change you make
to this control Now look at the SqlDataSource control Listing 7-46 shows you the root element of
this control
Trang 8Listing 7-46: Adding delete functionality to the SqlDataSource Control
<asp:SqlDataSource ID="SqlDataSource1" Runat="server"
SelectCommand="SELECT * FROM [Customers]"
ConnectionString="<%$ ConnectionStrings:AppConnectionString1 %>"
DataSourceMode="DataSet"
DeleteCommand="DELETE From Customers WHERE (CustomerID = @CustomerID)"
UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName,
[ContactName] = @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] = @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone, [Fax] = @Fax WHERE [CustomerID] = @original_CustomerID">
In addition to theSelectCommandandUpdateCommandattributes, you also add theDeleteCommand
attribute to the SqlDataSource and provide the SQL command that deletes the specified row Just like the
UpdateCommandproperty, theDeleteCommandproperty makes use of named parameters Because of this,
you define this parameter from within the SqlDataSource control To do this, add a<DeleteParameters>
section to the SqlDataSource control This is shown in Listing 7-47
Listing 7-47: Adding a<DeleteParameters> section to the SqlDataSource control
<DeleteParameters>
<asp:Parameter Name="CustomerID" Type="String">
</asp:Parameter>
</DeleteParameters>
This is the only parameter definition needed for the<DeleteParameters>section because the SQL
command for this deletion requires only the CustomerID from the row to delete the entire row
When you run the example with this code in place, you see a Delete link next to the Edit link Clicking
the Delete link completely deletes the selected row Remember that it is a good idea to check for database
errors after you complete the deletion Listing 7-48 shows how you can use the GridView’sRowDeleted
event and the SqlDataSourcesDeletedevent to check for errors that might have occurred during the
Delete
Notice that both events provide Exception properties to you as part of the event arguments If the
prop-erties are not empty, then an exception occurred that you can handle If you do choose to handle the
exception, then you should set theExceptionHandledproperty toTrue; otherwise, the exception will
continue to bubble up to the end user
Listing 7-48: Using the RowDeleted event to catch SQL errors
VB
<script runat="server">
Protected Sub GridView1_RowDeleted(ByVal sender As Object, _
ByVal e As GridViewDeletedEventArgs)
If (Not IsDBNull (e.Exception)) Then Me.lblErrorMessage.Text = e.Exception.Message e.ExceptionHandled = True
End If
Trang 9End Sub
Protected Sub SqlDataSource1_Deleted(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs)
If (e.Exception IsNot Nothing) Then Me.lblErrorMessage.Text = e.Exception.Message e.ExceptionHandled = True
End If End Sub
</script>
C#
<script runat="server">
protected void GridView1_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
if (e.Exception != null) {
this.lblErrorMessage.Text = e.Exception.Message;
e.ExceptionHandled = true;
} }
protected void SqlDataSource1_Deleted(object sender,
SqlDataSourceStatusEventArgs e) {
if (e.Exception != null) {
this.lblErrorMessage.Text = e.Exception.Message;
e.ExceptionHandled = true;
} }
</script>
Other GridView Formatting Features
The GridView control includes numerous other properties that let you adjust the look and feel of the con-trol in fine detail TheCaptionproperty allows you to set a caption at the top of the grid TheShowHeader andShowFooterproperties enable you to control whether the column headers or footers are shown The
control also includes eight different style properties that give you control over the look and feel of different
parts of the grid The following table describes the style properties
Style Property Description
AlternatingRowStyle Style applied to alternating GridView rows
EditRowStyle Style applied to a GridView row in edit mode
EmptyDataRowStyle Style applied to the EmptyDataRow when there are datarows
available for the grid to bind to FooterStyle Style applied to the footer of the GridView
HeaderStyle Style applied to the header of the GridView
Trang 10Style Property Description
PagerStyle Style applied to the GridView pager
RowStyle Style applied to the default GridView row
SelectedRowStyle Style applied to the currently selected GridView row
These style properties let you set the font, forecolor, backcolor, alignment, and many other style-related
properties for these individual areas of the grid
The GridView smart tag also includes an AutoFormat option that enables you to select from a list of
predefined styles to apply to the control
DetailsView
The DetailsView server control is a new data-bound control that enables you to view a single data record
at a time Although the GridView control is an excellent control for viewing a collection of data, many
scenarios demand that you be able to drill down into an individual record The DetailsView control
allows you to do this and provides many of the same data manipulation and display capabilities as the
GridView It allows you to do things such as paging, updating, inserting, and deleting data
To start using the DetailsView, drag the control onto the design surface Like the GridView, you can use
the DetailsView’s smart tag to create and set the data source for the control For this sample, just
use the SqlDataSource control you used for the GridView If you run the page at this point, you see that
the control displays one record, the first record returned by your query Figure 7-27 shows you what the
DetailsView looks like in a Web page
Figure 7-27