Recipe 2.14. Editing Data Within a DataGrid


Problem

You want to allow the user to edit the data within the table displayed by a DataGrid.

Solution

Add an EditCommandColumn column type to the DataGrid control's display to enable editing of the data fields of each record. A typical example of normal display mode output is shown in Figure 2-14, and an example of edit mode output is shown in Figure 2-15. Examples 2-36, 2-37 through 2-38 show the .aspx and code-behind files for the application that produces this result.

Figure 2-14. DataGrid with editingnormal mode


Figure 2-15. DataGrid with editingrow edit mode


Discussion

This recipe uses the built-in editing facilities of the DataGrid control, in particular the EditCommandColumn column type, which provides Edit command buttons for editing data items in each row of a DataGrid. The EditText, CancelText, and UpdateText properties define the text to be output for the Edit command button's Edit, Cancel, and Update hyperlinks, respectively.

 <asp:EditCommandColumn ButtonType="LinkButton"   EditText="Edit"   CancelText="Cancel"   UpdateText="Update" /> 

The ButtonType attribute defines the type of button to output. You can specify LinkButton, which provides hyperlinked text, or PushButton, which outputs an HTML button.

The Edit command button's EditText, CancelText, and UpdateText properties can be set to HTML. For example, to output an image for the links, you can use <img src="/books/1/505/1/html/2/images/buttons/editButton.gif" border="0" alt="Edit"/>.


In our example that implements this solution, three columns are defined for the DataGrid. The first uses an asp:BoundColumn element with the ReadOnly attribute set to true to prevent users from editing the field contents:

 <asp:BoundColumn DataField="SectionNumber" ItemStyle-HorizontalAlign="Center" HeaderText="Section" ReadOnly="True" /> 

The second column uses an asp:TemplateColumn element to define a layout template for normal display (ItemTemplate) and edit mode display (EditItemTemplate). The EditItemTemplate property defines an asp:TextBox control to control the size and other aspects of the field contents. Both templates are bound to the "SectionHeading" data.

 <asp:TemplateColumn HeaderText="Section Heading"> <ItemTemplate> <%#Eval("SectionHeading")%> </ItemTemplate> <EditItemTemplate> <asp:TextBox  runat="server"         Columns="55" css text='<%# Eval("SectionHeading") %>' /> </EditItemTemplate> </asp:TemplateColumn> 

Like the second column, the third column uses an asp:TemplateColumn element. In this case, however, the EditItemTemplate property defines an asp:DropDownList control, allowing the user to select only from valid choices for the column. This column is bound to the yesNoSelections ArrayList created in the code-behind. The selection in the drop-down list is initialized to the current value in the database by binding the SelectedIndex to the index of the value in the ArrayList.

 <asp:TemplateColumn HeaderText="VB Example"    ItemStyle-HorizontalAlign="Center">      <ItemTemplate> <%#yesNoSelections.Item(CInt(Eval("HasVBExample")))%>  </ItemTemplate>  <EditItemTemplate> <asp:DropDownList  runat="server" DataSource="<%# yesNoSelections %>" DataTextField="Text" DataValueField="Value" SelectedIndex='<%# CInt(Eval("HasVBExample")) %>' /> </EditItemTemplate> </asp:TemplateColumn> 

The Protected yesNoSelections As ArrayList declaration is added at the class level in the code-behind to provide access to the ArrayList from the code in the .aspx file.

Page_Load just calls bindData, as is typical in this chapter's recipes. However, bindData is different from the norm in two ways. First, the ArrayList is built with the selections that are applicable for the user to select from when changing the value of the Has VB Example column. Second, the line dgProblems.DataKeyField = "EditProblemID" is added to have the DataGrid maintain the primary key value for each row without having to add it to the grid as a column (hidden or visible). This approach stores the primary key value for each row in the view state only so it can be recovered when needed on the server side. It has the advantage of hiding the value from prying eyes.

The dgProblems_EditCommand method handles the event generated when the user clicks the Edit link within a row. It sets the EditItemIndex to the selected row, which causes ASP.NET to use the Edit Template when the data for the row is rebound along with the Cancel and Update links in the edit command column.

The dgProblems_CancelCommand method handles the event generated when the user clicks the Cancel link in the row being edited. It sets the EditItemIndex to 1 to display the DataGrid in normal mode when the data is rebound.

The dgProblems_UpdateCommand method handles the event generated when the user clicks the Update link in the row being edited. It extracts the edited data, updates the data in the database, and resets the DataGrid to normal mode when the data is rebound (see comments in the code for more details).

Example 2-36. DataGrid with editing (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master" AutoEventWireup="false" CodeFile="CH02DataGridWithEditingVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH02DataGridWithEditingVB" Title="DataGrid With Editing" %> <asp:Content  Runat="server" ContentPlaceHolder> <div align="center" > DataGrid With Editing (VB) </div> <asp:DataGrid  runat="server"  BorderColor="#000080" BorderWidth="2px"  AutoGenerateColumns="False"  HorizontalAlign="center"  Width="90%"  OnCancelCommand="dgProblems_CancelCommand"  OnEditCommand="dgProblems_EditCommand"  OnUpdateCommand="dgProblems_UpdateCommand"> <HeaderStyle HorizontalAlign="Center" Css /> <ItemStyle css /> <AlternatingItemStyle css /> <Columns> <asp:BoundColumn DataField="SectionNumber" ItemStyle-HorizontalAlign="Center" HeaderText="Section" ReadOnly="True" /> <asp:TemplateColumn HeaderText="Section Heading"> <ItemTemplate> <%#Eval("SectionHeading")%> </ItemTemplate> <EditItemTemplate> <asp:TextBox  runat="server" Columns="55" css text='<%# Eval("SectionHeading") %>' /> </EditItemTemplate> </asp:TemplateColumn> <asp:TemplateColumn HeaderText="VB Example"    ItemStyle-HorizontalAlign="Center">        <ItemTemplate>   <%#yesNoSelections.Item(CInt(Eval("HasVBExample")))%>    </ItemTemplate>    <EditItemTemplate>    <asp:DropDownList  runat="server"    DataSource="<%# yesNoSelections %>"    DataTextField="Text"    DataValueField="Value"     SelectedIndex='<%# CInt(Eval("HasVBExample")) %>' /> </EditItemTemplate> </asp:TemplateColumn> <asp:EditCommandColumn ButtonType="LinkButton"   EditText="Edit"   CancelText="Cancel"   UpdateText="Update" /> </Columns> </asp:DataGrid> </asp:Content> 

Example 2-37. DataGrid with editing code-behind (.vb)

 Option Explicit On Option Strict On  Imports Microsoft.VisualBasic  Imports System.Configuration  Imports System.Data  Imports System.Data.OleDb Namespace ASPNetCookbook.VBExamples  ''' <summary>  ''' This class provides the code behind for  ''' CH02DataGridWithEditingVB.aspx  ''' </summary> Partial Class CH02DataGridWithEditingVB Inherits System.Web.UI.Page 'The following variable contains the list of yes/no selections used in 'the dropdown lists and is declared protected to provide access to the 'data from the aspx page Protected yesNoSelections As ArrayList '''**************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Private Sub Page_Load(ByVal sender As Object, _   ByVal e As System.EventArgs) Handles Me.Load    If (Not Page.IsPostBack) Then    bindData()    End If End Sub 'Page_Load '''**************************************************************** ''' <summary> ''' This routine provides the event handler for the cancel command click ''' event. It is responsible for resetting the edit item index to no item ''' and rebinding the data. ''' </summary> ''' ''' <param name="source">Set to the source of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub dgProblems_CancelCommand(ByVal source As Object, _ ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) dgProblems.EditItemIndex = -1 bindData() End Sub 'dgProblems_CancelCommand '''**************************************************************** ''' <summary> ''' This routine provides the event handler for the edit command click ''' event. It is responsible for setting the edit item index to the ''' selected item and rebinding the data. ''' </summary> ''' ''' <param name="source">Set to the source of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub dgProblems_EditCommand(ByVal source As Object, _ ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) dgProblems.EditItemIndex = e.Item.ItemIndex bindData() End Sub 'dgProblems_EditCommand '''****************************************************************     ''' <summary> ''' This routine provides the event handler for the update command click ''' event. It is responsible for updating the contents of the database ''' with the date entered for the item currently being edited. ''' </summary> ''' ''' <param name="source">Set to the source of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub dgProblems_UpdateCommand(ByVal source As Object, _ ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Dim dbConn As OleDbConnection = Nothing  Dim dCmd As OleDbCommand = Nothing  Dim sectionHeading As String  Dim hasVBSample As Integer  Dim strConnection As String  Dim strSQL As String  Dim rowsAffected As Integer Try 'get the edited section heading and "has vb sample" data 'NOTE: This can be done by using the FindControl method of the edited '    item because EditItemTemplates were used and the controls in the '    templates where given IDs. If a standard BoundColumn was used, '    the data would have to be acccessed using the cells collection '    (e.g. e.Item.Cells(0).Text would access the section number '    column in this example. sectionHeading = CType(e.Item.FindControl("txtSectionHeading"), _     TextBox).Text( ) hasVBSample = CInt(CType(e.Item.FindControl("selHasVBSample"), _  DropDownList).SelectedItem.Value) 'get the connection string from web.config and open a connection 'to the database strConnection = ConfigurationManager. _ ConnectionStrings("dbConnectionString").ConnectionString dbConn = New OleDbConnection(strConnection) dbConn.Open( ) 'update data in database 'NOTE: The primary key used to uniquely identify the row being edited ' is accessed through the DataKeys collection of the DataGrid. strSQL = "UPDATE EditProblem " & _  "SET SectionHeading=?" & _  ",HasVBExample=?" & _  " WHERE EditProblemSectionHeading", sectionHeading)) dCmd.Parameters.Add(New OleDbParameter("HasVBSample", hasVBSample)) rowsAffected = dCmd.ExecuteNonQuery( ) 'TODO: production code should check the number of rows affected here to 'make sure it is exactly 1 and output the appropriate success or 'failure information to the user. 'reset the edit item and rebind the data dgProblems.EditItemIndex = -1 bindData( ) Finally 'cleanup   If (Not IsNothing(dbConn)) Then dbConn.Close( )   End If  End Try    End Sub 'dgProblems_UpdateCommand       '''*************************************************************    ''' <summary>    ''' This routine queries the database for the data to displayed and    ''' binds it to the DataGrid.    ''' </summary>    Private Sub bindData( ) Dim dbConn As OleDbConnection = Nothing Dim da As OleDbDataAdapter = Nothing Dim dTable As DataTable = Nothing Dim strConnection As String Dim strSQL As String Try 'get the connection string from web.config and open a connection 'to the database strConnection = ConfigurationManager. _ ConnectionStrings("dbConnectionString").ConnectionString dbConn = New OleDbConnection(strConnection) dbConn.Open( ) 'build the query string and get the data from the database strSQL = "SELECT EditProblemID, SectionNumber" & _  ", SectionHeading, HasVBExample" & _  " FROM EditProblem" & _  " ORDER BY SectionNumber"   da = New OleDbDataAdapter(strSQL, dbConn) dTable = New DataTable da.Fill(dTable) 'build the arraylist with the acceptable responses to the '"Has VB Sample" field yesNoSelections = New ArrayList(2) yesNoSelections.Add(New ListItem("No", "0")) yesNoSelections.Add(New ListItem("Yes", "1"))\ 'set the source of the data for the datagrid control and bind it dgProblems.DataSource = dTable dgProblems.DataKeyField = "EditProblemID" dgProblems.DataBind( ) Finally 'cleanup If (Not IsNothing(dbConn)) Then dbConn.Close( ) End If End Try End Sub 'bindData End Class 'CH02DataGridWithEditingVB End Namespace 

Example 2-38. DataGrid with editing code-behind (.cs)

 using System; using System.Collections; using System.Configuration; using System.Data; using System.Data.OleDb; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the code behind for /// CH02DataGridWithEditingCS.aspx /// </summary> public partial class CH02DataGridWithEditingCS : System.Web.UI.Page { // The following variable contains the list of yes/no selections used in // the dropdown lists and is declared protected to provide access to the // data from the aspx page protected ArrayList yesNoSelections; ///**************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { bindData( ); } } // Page_Load ///**************************************************************** /// <summary> /// This routine provides the event handler for the cancel command click /// event. It is responsible for resetting the edit item index to no item /// and rebinding the data. /// </summary> /// /// <param name="source">Set to the source of the event</param> /// <param name="e">Set to the event arguments</param> protected void dgProblems_CancelCommand(Object source,   System.Web.UI.WebControls.DataGridCommandEventArgs e)      { dgProblems.EditItemIndex = -1; bindData( ); } // dgProblems_CancelCommand ///**************************************************************** /// <summary> /// This routine provides the event handler for the edit command click /// event. It is responsible for setting the edit item index to the /// selected item and rebinding the data. /// </summary> /// /// <param name="source">Set to the source of the event</param> /// <param name="e">Set to the event arguments</param> protected void dgProblems_EditCommand(Object source,   System.Web.UI.WebControls.DataGridCommandEventArgs e)     { dgProblems.EditItemIndex = e.Item.ItemIndex; bindData( ); } // dgProblems_EditCommand ///**************************************************************** /// <summary> /// This routine provides the event handler for the update command click /// event. It is responsible for updating the contents of the database /// with the date entered for the item currently being edited. /// </summary> /// /// <param name="source">Set to the source of the event</param> /// <param name="e">Set to the event arguments</param> protected void dgProblems_UpdateCommand(Object source,   System.Web.UI.WebControls.DataGridCommandEventArgs e) { OleDbConnection dbConn = null; OleDbCommand dCmd = null; String sectionHeading = null; int hasCSSample; String strConnection = null; String strSQL = null; int rowsAffected; DropDownList ddl = null; try { // get the edited section heading and "has vb sample" data // NOTE: This can be done by using the FindControl method of the edited //  item because EditItemTemplates were used and the controls in //  the templates where given IDs. If a standard BoundColumn was //  used, the data would have to be acccessed using the cells //  collection (e.g. e.Row.Cells(0).Text would access the section //  number column in this example. sectionHeading = ((TextBox)(e.Item.FindControl("txtSectionHeading"))).Text; ddl = (DropDownList)(e.Item.FindControl("selHasCSSample")); hasCSSample = Convert.ToInt32(ddl.SelectedItem.Value); // get the connection string from web.config and open a connection // to the database strConnection = ConfigurationManager. ConnectionStrings["dbConnectionString"].ConnectionString; dbConn = new OleDbConnection(strConnection); dbConn.Open( ); // update data in database // NOTE: The primary key used to uniquely identify the row being edited //  is accessed through the DataKeys collection of the DataGrid. strSQL = "UPDATE EditProblem " +  "SET SectionHeading='" + sectionHeading + "'" +  ",HasCSExample=" + hasCSSample +  " WHERE EditProblemdbConnectionString"].ConnectionString; dbConn = new OleDbConnection(strConnection); dbConn.Open( ); // build the query string and get the data from the database strSQL = "SELECT EditProblemID, SectionNumber" +  ", SectionHeading, HasCSExample " +  "FROM EditProblem " +  "ORDER BY SectionNumber";  da = new OleDbDataAdapter(strSQL, dbConn);  dTable = new DataTable( );  da.Fill(dTable);  // build the arraylist with the acceptable responses to the  // "Has C# Sample" field  yesNoSelections = new ArrayList(2);  yesNoSelections.Add(new ListItem("No", "0"));  yesNoSelections.Add(new ListItem("Yes", "1"));    // set the source of the data for the datagrid control and bind it  dgProblems.DataSource = dTable;  dgProblems.DataKeyField = "EditProblemID";  dgProblems.DataBind( ); } // try finally { //clean up if (dbConn != null) { dbConn.Close( ); } } // finally } // bindData } // CH02DataGridWithEditingCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net