Recipe 2.20. Allowing Selection Anywhere Within a GridView


Problem

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

Solution

To every row in the GridView, 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 ButtonField to the GridView.

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

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

The approach produces output like that shown in Figure 2-21. Examples 2-51, 2-52 through 2-53 show the .aspx and code-behind files for the application that produces this result.

Figure 2-21. Output of GridView allowing selection anywhere


Discussion

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

 <Columns> <asp:ButtonField ButtonType="Link" Visible="False" CommandName="Select" /> … </Columns> 

In the code-behind, the GridView control's RowDataBound event handler (gvBooks_RowDataBound) 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 GridView, 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, you must first 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 two purposes are to handle the onclick event for the row in the GridView that has been data bound and to perform a call to__doPostBack. The JavaScript is added to the GridView 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) to be executed when the event occurs.

The Page's GetPostBackClientHyperlink method is used to get the name of the clientside 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 GridView, for example, the GetPostBackClientHyperlink method returns javascript:__doPostBack('ctl00$PageBody$gvBooks$ctl02$ctl00','').

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 GridView 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.


By default, ASP.NET 2.0 validates that events are raised only by controls that are enabled and are in parent hierarchies that are also enabled. Since the technique described in this recipe uses an event posted back from a hidden button, an exception will be thrown unless event validation is disabled by setting the EnableEventValidation attribute of the @ Page directive to false:

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB. master" AutoEventWireup="false" CodeFile="CH02GridViewWithSelectionAnywhereVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples. CH02GridViewWithSelectionAnywhereVB" EnableEventValidation="false" Title="GridView With Selection Anywhere" %> 


This example shows the use of Add, Edit, and Delete buttons below the GridView, 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 2-51. GridView allowing selection anywhere (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"   AutoEventWireup="false"   CodeFile="CH02GridViewWithSelectionAnywhereVB.aspx.vb"   Inherits="ASPNetCookbook.VBExamples.CH02GridViewWithSelectionAnywhereVB"   EnableEventValidation="false"   Title="GridView With Selection Anywhere" %> <asp:Content  Runat="server" ContentPlaceHolder> <div align="center" > GridView With Selection Anywhere (VB) </div> <asp:GridView  Runat="Server"   AllowPaging="false"   AllowSorting="false"   AutoGenerateColumns="false"   BorderColor="#000080"   BorderStyle="Solid"   BorderWidth="2px"   Caption=""   HorizontalAlign="Center"   Width="90%"   OnRowDataBound="gvBooks_RowDataBound" > <HeaderStyle HorizontalAlign="Center" Css /> <RowStyle css /> <AlternatingRowStyle css /> <SelectedRowStyle Css /> <Columns>   <asp:ButtonField ButtonType="Link"    Visible="False"    CommandName="Select" />   <asp:BoundField HeaderText="Title"    DataField="Title"    ItemStyle-HorizontalAlign="Left" />   <asp:BoundField HeaderText="Publish Date"    DataField="PublishDate"    ItemStyle-HorizontalAlign="Center"    DataFormatString="{0:MMM dd, yyyy}"/>   <asp:BoundField HeaderText="List Price"    DataField="ListPrice"    ItemStyle-HorizontalAlign="Center"    DataFormatString="{0:C2}"/> </Columns>    </asp:GridView>    <br />    <table width="40%" border="0" align="center"> <tr> <td align="center"> <input  runat="server" type="button" value="Add" onserverclick="btnAdd_ServerClick"> </td> <td align="center"> <input  runat="server" type="button" value="Edit" onserverclick="btnEdit_ServerClick"> </td> <td align="center"> <input  runat="server" type="button" value="Delete" onserverclick="btnDelete_ServerClick">  </td>    </tr>   </table> </asp:Content> 

Example 2-52. GridView allowing selection anywhere 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 ''' CH02GridViewWithSelectionAnywhereVB.aspx ''' </summary> Partial Class CH02GridViewWithSelectionAnywhereVB Inherits System.Web.UI.Page '''*********************************************************************** ''' <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 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 is the event handler that is called when the Add button ''' is clicked. ''' </summary> ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub btnAdd_ServerClick(ByVal sender As Object, _  ByVal e As System.EventArgs) _    'place code here to perform Add operations  End Sub 'btnAdd_ServerClick  '''***********************************************************************  ''' <summary>  ''' This routine is the event handler that is called when the Edit button  ''' is clicked.  ''' </summary>  ''' <param name="sender">Set to the sender of the event</param>  ''' <param name="e">Set to the event arguments</param>  Protected Sub btnEdit_ServerClick(ByVal sender As Object, _    ByVal e As System.EventArgs) _ 'place code here to perform Edit operations  End Sub 'btnEdit_ServerClick  '''***********************************************************************  ''' <summary>  ''' This routine is the event handler that is called when the Delete button  ''' is clicked.  ''' </summary>  ''' <param name="sender">Set to the sender of the event</param>  ''' <param name="e">Set to the event arguments</param>  Protected Sub btnDelete_ServerClick(ByVal sender As Object, _  ByVal e As System.EventArgs) _ 'place code here to perform Delete operations  End Sub 'btnDelete_ServerClick  '''***********************************************************************  ''' <summary>  ''' This routine provides the event handler for the GridView's row data  ''' bound event. It is responsible for formatting the data in the  ''' columns of the GridView  ''' </summary>  '''  ''' <param name="sender">Set to the sender of the event</param>  ''' <param name="e">Set to the event arguments</param>  Protected Sub gvBooks_RowDataBound(ByVal sender As Object, ByVal e As _ System.Web.UI.WebControls.GridViewRowEventArgs) 'GridView 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 GridView If (e.Row.RowType = DataControlRowType.DataRow) Then   'the item that was bound is a so get a reference to the link button   'column defined in the Columns property of the GridView (in the aspx   'file) 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.Row.Cells(LINK_BUTTON_COLUMN).Controls(LINK_BUTTON_CONTROL), _ LinkButton) e.Row.Attributes.Add("onclick", _   ClientScript.GetPostBackClientHyperlink(button, ""))   End If End Sub 'gvBooks_RowDataBound '''*********************************************************************** ''' <summary> ''' This routine queries the database for the data to displayed and binds ''' it to the GridView ''' </summary> Private Sub bindData( )   Dim dSource As SqlDataSource = Nothing   'configure the data source to get the data from the database   dSource = New SqlDataSource( )   dSource.ConnectionString = ConfigurationManager. _      ConnectionStrings("dbConnectionString").ConnectionString   dSource.DataSourceMode = SqlDataSourceMode.DataSet   dSource.ProviderName = "System.Data.OleDb"   dSource.SelectCommand = "SELECT Title, PublishDate, ListPrice " & _   "FROM Book " & _   "ORDER BY Title"   'set the source of the data for the gridview control and bind it    gvBooks.DataSource = dSource    gvBooks.DataBind( ) 'select first item in the gridview gvBooks.SelectedIndex = 0   End Sub 'bindData End Class 'CH02GridViewWithSelectionAnywhereVB End Namespace 

Example 2-53. GridView allowing selection anywhere code-behind (.cs)

 using System; 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 /// CH02GridViewWithSelectionAnywhereCS.aspx /// </summary> public partial class CH02GridViewWithSelectionAnywhereCS : System.Web.UI.Page { ///*********************************************************************** /// <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 is the event handler that is called when the Add button /// is clicked. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnAdd_ServerClick(Object sender,   System.EventArgs e) { // place code here to perform Add operations } // btnAdd_ServerClick ///*********************************************************************** /// <summary> /// This routine is the event handler that is called when the Edit button /// is clicked. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnEdit_ServerClick(Object sender,    System.EventArgs e) { // place code here to perform Edit operations } // btnEdit_ServerClick ///*********************************************************************** /// <summary> /// This routine is the event handler that is called when the Delete button /// is clicked. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnDelete_ServerClick(Object sender,  System.EventArgs e) { // place code here to perform Delete operations } // btnDelete_ServerClick ///*********************************************************************** /// <summary> /// This routine provides the event handler for the GridView's row created /// event. It is responsible for setting the icon in the header row to /// indicate the current sort column and sort order /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void gvBooks_RowDataBound(Object sender, System.Web.UI.WebControls.GridViewRowEventArgs e) { // gridview 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 row that was databound and only take action if it // was a data row if (e.Row.RowType == DataControlRowType.DataRow) { // the item that was bound is a data 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.Row.Cells[LINK_BUTTON_COLUMN].Controls[LINK_BUTTON_CONTROL]); e.Row.Attributes.Add("onclick", Page.GetPostBackClientHyperlink(button, "")); } } //gvBooks_RowDataBound ///*********************************************************************** /// <summary> /// This routine queries the database for the data to displayed and /// binds it to the GridView /// </summary> private void bindData( ) { SqlDataSource dSource = null; // configure the data source to get the data from the database dSource = new SqlDataSource( ); dSource.ConnectionString = ConfigurationManager. ConnectionStrings["dbConnectionString"].ConnectionString; dSource.DataSourceMode = SqlDataSourceMode.DataReader; dSource.ProviderName = "System.Data.OleDb"; dSource.SelectCommand = "SELECT Title, PublishDate, ListPrice " +      "FROM Book " +  "ORDER BY Title"; // set the source of the data for the gridview control and bind it gvBooks.DataSource = dSource; gvBooks.DataBind( ); // select first item in the gridview gvBooks.SelectedIndex = 0; } // bindData } // CH02GridViewWithSelectionAnywhereCS } 



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

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