Recipe 1.16 Allowing Selection Anywhere Within a DataGrid Row

     

Recipe 1.16 Allowing Selection Anywhere Within a DataGrid Row

1.16.1 Problem

You are implementing a DataGrid that requires selection of a row, but you do not want to have a Select button in every row of your DataGrid . What you really want is to allow the user to click anywhere within a row, like in a classic Windows application.

1.16.2 Solution

To every row in the DataGrid add a hidden Select button along with an onclick event that performs the same action as if the hidden Select button were clicked.

  1. Add a hidden ButtonColumn to the DataGrid .

  2. Set the ButtonType attribute to " LinkButton " so that a hidden hyperlinked Select button is rendered in every row.

  3. In the ItemDataBound event, add an onclick event to the DataGrid row that performs the same action as clicking the hidden Select button.

The approach produces output like that shown in Figure 1-20. Example 1-45 through Example 1-47 show the .aspx and code-behind files for the application that produces this result.

Figure 1-20. Output of DataGrid allowing selection anywhere
figs/ancb_0120.gif

1.16.3 Discussion

To allow selection of a row of data simply by clicking on it, you create a DataGrid in the usual fashion but add a hidden ButtonColumn . The ButtonType attribute is set to " LinkButton ", and the CommandName attribute is set to " Select ". This causes the DataGrid to be rendered with a hidden hyperlinked Select button in every row.

 <Columns>  <asp:ButtonColumn ButtonType="LinkButton"   Visible="False"   CommandName="Select" />  ... </Columns> 

In the code-behind, the DataGrid control's ItemDataBound event handler ( dgProblems_ItemDataBound ) is used to expand the functionality of the hidden Select button to encompass the entire row. This method is called for every row of the DataGrid , including the header and footer, so the item type must be checked to see if this event applies to a given data row.

When the event applies to a data row, the first thing you must do is get a reference to the hidden Select button in the row. The LINK_BUTTON_COLUMN and LINK_BUTTON_CONTROL constants are used to avoid so-called "magic numbers" (hardcoded numbers that seem to appear out of nowhere in the code) and to make the code more maintainable .

Next, some client-side JavaScript is added to a row's hidden hyperlinked Select button. Its sole purpose is to handle the onclick event for the row in the DataGrid that has just been data bound and to perform a call to _ _doPostBack . The JavaScript is added to the DataGrid row's Attributes collection using the Add method, whose parameters are the name of the event we want to add to the control and the name of the function (along with its parameters) that is to be executed when the event occurs.

The Page 's GetPostBackClientHyperlink method is used to get the name of the client-side function created for the hidden Select button in the row being processed . It returns the name of the event method along with the required parameters. For the first row in our DataGrid , for example, the GetPostBackClientHyperlink method returns javascript:_ _doPostBack('dgProblems:_ctl2:_ctl0','') .

Effectively, this adds an onclick event to all the table rows, which causes the method _ _doPostBack to be called anytime the user clicks on a data row in the grid. Because this onclick event is identical to the event created for the hidden Select button in the row, the postback is processed as a select event, thereby setting the SelectedIndex of the DataGrid to the clicked row.

Be aware that the selection of a row using this method requires a round trip to the server to perform the selection.


This example shows the use of Add, Edit, and Delete buttons below the DataGrid , which is typical of a scenario where a row is selected and then a desired action is performed on it. The methods for the Add, Edit, and Delete events were included in this recipe but were left empty to keep the code down to a reasonable size .

Example 1-45. DataGrid allowing selection anywhere (.aspx)
 <%@ Page Language="vb" AutoEventWireup="false"      Codebehind="CH01DatagridWithSelectionAnywhereVB.aspx.vb"      Inherits="ASPNetCookbook.VBExamples.CH01DatagridWithSelectionAnywhereVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>   <head>     <title>DataGrid With Selection Anywhere</title>     <link rel="stylesheet" href="css/ASPNetCookbook.css">   </head>   <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">     <form id="frmDatagrid" method="post" runat="server">       <table width="100%" cellpadding="0" cellspacing="0" border="0">         <tr>           <td align="center">             <img src="images/ASPNETCookbookHeading_blue.gif">           </td>         </tr>         <tr>           <td class="dividerLine">             <img src="images/spacer.gif" height="6" border="0"></td>         </tr>       </table>       <table width="90%" align="center" border="0">         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td align="center" class="PageHeading">             DataGrid With Selection Anywhere (VB)           </td>         </tr>         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td align="center">                 <!-- The first column defined in the Columns element is a                       hidden link button to provide the ability to make                       clicking anywhere in the row the same as clicking                       the link button.  See the dgProblems_ItemDataBound                       method in the code behind page -->  <asp:DataGrid   id="dgProblems"   runat="server"   BorderColor="000080"   BorderWidth="2px"   AutoGenerateColumns="False"   width="100%">   <HeaderStyle   HorizontalAlign="Center"   ForeColor="#FFFFFF"   BackColor="#000080"   Font-Bold=true   CssClass="TableHeader" />   <ItemStyle   BackColor="#FFFFE0"   cssClass="TableCellNormal" />   <AlternatingItemStyle   BackColor="#FFFFFF"   cssClass="TableCellAlternating" />   <SelectedItemStyle   BackColor="#cccccc"   cssClass="TableCellAlternating" />     <Columns>   <asp:ButtonColumn ButtonType="LinkButton"   Visible="False"   CommandName="Select" />   <asp:BoundColumn HeaderText="Title"   DataField="Title"   ItemStyle-HorizontalAlign="Left" />   <asp:BoundColumn HeaderText="Publish Date"   DataField="PublishDate"   ItemStyle-HorizontalAlign="Center"   DataFormatString="{0:MMM dd, yyyy}"/>   <asp:BoundColumn HeaderText="List Price"   DataField="ListPrice"   ItemStyle-HorizontalAlign="Center"   DataFormatString="{0:C2}"/>   </Columns>     </asp:DataGrid>  </td>         </tr>         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td align="center">             <table width="100%">               <tr>                 <td width="18%">&nbsp;</td>                 <td width="15%" align="center">                   <asp:ImageButton id="btnAdd" runat="server"                         ImageUrl="images/buttons/button_add.gif" /></td>                 <td width="10%">&nbsp;</td>                 <td width="15%" align="center">                   <asp:ImageButton id="btnEdit" runat="server"                         ImageUrl="images/buttons/button_edit.gif" /></td>                 <td width="10%">&nbsp;</td>                 <td width="15%" align="center">                   <asp:ImageButton id="btnDelete" runat="server"                         ImageUrl="images/buttons/button_delete.gif" /></td>                 <td width="17%">&nbsp;</td>               </tr>             </table>           </td>         </tr>       </table>     </form>   </body> </html> 

Example 1-46. DataGrid allowing selection anywhere code-behind (.vb)
 Option Explicit On  Option Strict On '----------------------------------------------------------------------------- ' '   Module Name: CH01DatagridWithSelectionAnywhereVB.aspx.vb ' '   Description: This class provides the code behind for '                CH01DatagridWithSelectionAnywhereVB ' '***************************************************************************** Imports Microsoft.VisualBasic Imports System.Configuration Imports System.Data Imports System.Data.OleDb Imports System.Web.UI.WebControls Namespace ASPNetCookbook.VBExamples   Public Class CH01DatagridWithSelectionAnywhereVB     Inherits System.Web.UI.Page     'controls on form     Protected WithEvents btnAdd As System.Web.UI.WebControls.ImageButton     Protected WithEvents btnEdit As System.Web.UI.WebControls.ImageButton     Protected WithEvents btnDelete As System.Web.UI.WebControls.ImageButton     Protected WithEvents dgProblems As System.Web.UI.WebControls.DataGrid     '*************************************************************************     '     '   ROUTINE: Page_Load     '     '   DESCRIPTION: This routine provides the event handler for the page load     '                event.  It is responsible for initializing the controls      '                on the page.     '-------------------------------------------------------------------------     Private Sub Page_Load(ByVal sender As System.Object, _                           ByVal e As System.EventArgs) _             Handles MyBase.Load       If (Not Page.IsPostBack) Then         bindData( )       End If     End Sub  'Page_Load     '*************************************************************************     '     '   ROUTINE: dgProblems_ItemDataBound     '     '   DESCRIPTION: This routine is the event handler that is called for      '                each item in the datagrid after a data bind occurs.  It      '                is responsible for making each row a link button to      '                allow clicking anywhere to select a row.     '-------------------------------------------------------------------------  Private Sub dgProblems_ItemDataBound(ByVal sender As Object, _   ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _   Handles dgProblems.ItemDataBound   'datagrid column containing link button defined on ASPX page   Const LINK_BUTTON_COLUMN As Integer = 0   'index of link button control in the link button column   Const LINK_BUTTON_CONTROL As Integer = 0   Dim button As LinkButton   'check the type of item that was databound and only take action if it   'was a row in the datagrid   If ((e.Item.ItemType = ListItemType.Pager) Or _   (e.Item.ItemType = ListItemType.Header) Or _   (e.Item.ItemType = ListItemType.Footer)) Then   'do nothing   Else   'the item that was bound is an "Item", "AlternatingItem", "EditItem",   '"SelectedItem" or "Separator" (in other words a row) so get a   'reference to the link button column defined in the Columns property   'of the datagrid (in the aspx page) and add an event handler for the   'the onclick event for this entire row.  This will make clicking   'anywhere in the row select the row.   'NOTE: This is tightly coupled to the definition of the bound columns   '      in the aspx page.   button = _   CType(e.Item.Cells(LINK_BUTTON_COLUMN).Controls(LINK_BUTTON_CONTROL), _   LinkButton)   e.Item.Attributes.Add("onclick", _   Page.GetPostBackClientHyperlink(button, ""))   End If   End Sub  'dgProblems_ItemDataBound  '*************************************************************************     '     '   ROUTINE: btnAdd_Click     '     '   DESCRIPTION: This routine is the event handler that is called when      '                the Add button is clicked.     '-------------------------------------------------------------------------     Private Sub btnAdd_Click(ByVal sender As Object, _                              ByVal e As System.Web.UI.ImageClickEventArgs) _                 Handles btnAdd.Click       'place code here to perform Add operations     End Sub  'btnAdd_Click     '*************************************************************************     '     '   ROUTINE: btnEdit_Click     '     '   DESCRIPTION: This routine is the event handler that is called when      '                the Edit button is clicked.     '-------------------------------------------------------------------------     Private Sub btnEdit_Click(ByVal sender As Object, _                               ByVal e As System.Web.UI.ImageClickEventArgs) _                 Handles btnEdit.Click       'place code here to perform Edit operations     End Sub  'btnEdit_Click     '*************************************************************************     '     '   ROUTINE: btnDelete_Click     '     '   DESCRIPTION: This routine is the event handler that is called when      '                the Delete button is clicked.     '-------------------------------------------------------------------------     Private Sub btnDelete_Click(ByVal sender As Object, _                                 ByVal e As System.Web.UI.ImageClickEventArgs) _                 Handles btnDelete.Click       'place code here to perform Delete operations     End Sub  'btnDelete_Click     '*************************************************************************     '     '   ROUTINE: bindData     '     '   DESCRIPTION: This routine queries the database for the data to      '                displayed and binds it to the datagrid     '     '-------------------------------------------------------------------------     Private Sub bindData( )       Dim dbConn As OleDbConnection       Dim dCmd As OleDbCommand       Dim dReader As OleDbDataReader       Dim strConnection As String       Dim strSQL As String       Try         'get the connection string from web.config and open a connection          'to the database         strConnection = _             ConfigurationSettings.AppSettings("dbConnectionString")         dbConn = New OleDb.OleDbConnection(strConnection)         dbConn.Open( )         'build the query string and get the data from the database         strSQL = "SELECT Title, PublishDate, ListPrice " & _                  "FROM Book " & _                  "ORDER BY Title"         dCmd = New OleDbCommand(strSQL, dbConn)         dReader = dCmd.ExecuteReader(CommandBehavior.Default)         'set the source of the data for the datagrid control and bind it         dgProblems.DataSource = dReader         dgProblems.DataBind( )         'select first item in the datagrid         dgProblems.SelectedIndex = 0       Finally         'cleanup         If (Not IsNothing(dReader)) Then           dReader.Close( )         End If         If (Not IsNothing(dbConn)) Then           dbConn.Close( )         End If       End Try     End Sub      'bindData   End Class  'CH01DatagridWithSelectionAnywhereVB End Namespace 

Example 1-47. DataGrid allowing selection anywhere code-behind (.cs)
 //---------------------------------------------------------------------------- // //   Module Name: CH01DatagridWithSelectionAnywhereCS.aspx.cs // //   Description: This class provides the code behind for //                CH01DatagridWithSelectionAnywhereCS.aspx // //**************************************************************************** using System; using System.Configuration; using System.Data; using System.Data.OleDb; using System.Web.UI; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples {   public class CH01DatagridWithSelectionAnywhereCS : System.Web.UI.Page   {     // controls on form     protected System.Web.UI.WebControls.ImageButton btnAdd;     protected System.Web.UI.WebControls.ImageButton btnEdit;     protected System.Web.UI.WebControls.ImageButton btnDelete;     protected System.Web.UI.WebControls.DataGrid dgProblems;     //************************************************************************     //     //   ROUTINE: Page_Load     //     //   DESCRIPTION: This routine provides the event handler for the page     //                load event.  It is responsible for initializing the     //                controls on the page.     //------------------------------------------------------------------------     private void Page_Load(object sender, System.EventArgs e)     {       // wire the item data bound and button events       this.dgProblems.ItemDataBound +=         new DataGridItemEventHandler(this.dgProblems_ItemDataBound);       this.btnAdd.Click +=         new ImageClickEventHandler(this.btnAdd_Click);       this.btnEdit.Click +=         new ImageClickEventHandler(this.btnEdit_Click);       this.btnDelete.Click +=         new ImageClickEventHandler(this.btnDelete_Click);       if (!Page.IsPostBack)       {         bindData( );       }     }  // Page_Load     //************************************************************************     //     //   ROUTINE: dgProblems_ItemDataBound     //     //   DESCRIPTION: This routine is the event handler that is called for     //                each item in the datagrid after a data bind occurs.  It     //                is responsible for making each row a link button to     //                allow clicking anywhere to select a row.     //------------------------------------------------------------------------  private void dgProblems_ItemDataBound(Object sender,   System.Web.UI.WebControls.DataGridItemEventArgs e)   {   // datagrid column containing link button defined on ASPX page   const int LINK_BUTTON_COLUMN = 0;   // index of link button control in the link button column   const int LINK_BUTTON_CONTROL = 0;   LinkButton button = null;   // check the type of item that was databound and only take action if it   // was a row in the datagrid   if ((e.Item.ItemType == ListItemType.Pager)   (e.Item.ItemType == ListItemType.Header)   (e.Item.ItemType == ListItemType.Footer))   {   // do nothing   }   else   {   // the item that was bound is an "Item", "AlternatingItem",   // "EditItem", "SelectedItem" or "Separator" (in other words a row)   // so get a reference to the link button column defined in the   // Columns property of the datagrid (in the aspx page) and add an   // event handler for the the onclick event for this entire row.  This   // will make clicking anywhere in the row select the row.   // NOTE: This is tightly coupled to the definition of the bound   //       columns in the aspx page.   button =   (LinkButton)(e.Item.Cells[LINK_BUTTON_COLUMN].Controls[LINK_BUTTON_CONTROL]);   e.Item.Attributes.Add("onclick",   Page.GetPostBackClientHyperlink(button, ""));   }   }  // dgProblems_ItemDataBound  //************************************************************************     //     //   ROUTINE: btnAdd_Click     //     //   DESCRIPTION: This routine is the event handler that is called when     //                the Add button is clicked.     //------------------------------------------------------------------------     private void btnAdd_Click(Object sender,       System.Web.UI.ImageClickEventArgs e)     {       // place code here to perform Add operations     }  // btnAdd_Click     //************************************************************************     //     //   ROUTINE: btnEdit_Click     //     //   DESCRIPTION: This routine is the event handler that is called when     //                the Edit button is clicked.     //------------------------------------------------------------------------     private void btnEdit_Click(Object sender,       System.Web.UI.ImageClickEventArgs e)     {       // place code here to perform Edit operations     }  // btnEdit_Click     //************************************************************************     //     //   ROUTINE: btnDelete_Click     //     //   DESCRIPTION: This routine is the event handler that is called when     //                the Delete button is clicked.     //------------------------------------------------------------------------     private void btnDelete_Click(Object sender,       System.Web.UI.ImageClickEventArgs e)     {       // place code here to perform Delete operations     }  // btnDelete_Click     //************************************************************************     //     //   ROUTINE: bindData     //     //   DESCRIPTION: This routine queries the database for the data to     //                displayed and binds it to the repeater     //------------------------------------------------------------------------     private void bindData( )     {       OleDbConnection dbConn = null;       OleDbCommand dCmd = null;       OleDbDataReader dReader = null;       String strConnection = null;       String strSQL =null;       try       {         // get the connection string from web.config and open a connection          // to the database         strConnection =            ConfigurationSettings.AppSettings["dbConnectionString"];         dbConn = new OleDbConnection(strConnection);         dbConn.Open( );         // build the query string and get the data from the database         strSQL = "SELECT Title, PublishDate, ListPrice " +                  "FROM Book " +                  "ORDER BY Title";         dCmd = new OleDbCommand(strSQL, dbConn);         dReader = dCmd.ExecuteReader(CommandBehavior.Default);         // set the source of the data for the datagrid control and bind it         dgProblems.DataSource = dReader;         dgProblems.DataBind( );         // select first item in the datagrid         dgProblems.SelectedIndex = 0;       }  // try       finally       {         // clean up         if (dReader != null)         {           dReader.Close( );         }         if (dbConn != null)         {           dbConn.Close( );         }       }  // finally     }  // bindData   }  // CH01DatagridWithSelectionAnywhereCS } 



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

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