AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=946&pId=-1
Extended GridView Control
page
by Bilal Haidar
Feedback
Average Rating: 
Views (Total / Last 10 Days): 94439/ 167

Introduction

This article focuses on explaining a set of features that have been added to the GridView controls that ship with ASP.NET 2.0.  Two main features among the list are the ContextMenu row-based and Filter Textbox to filter GridView’s rows.  During the last few weeks we have been working on extending the new GridView controls that ship with ASP.NET 2.0.

There are several production controls that offer the features that we have added to the GridView control.  However, none of those controls based their work on the GridView control.  As you have probably seen, those controls were always rebuilt from scratch.

Extending the current GridView control gives you more control over the GridView since nothing will be changed in the way you have been using the GridView control.  Rather, you will be able to add and use additional features that are needed from time to time.

We were able to add several new features, among which are:

1.      Single Row Click

2.      Double Row Click

3.      ContextMenu row-based

4.      Ascending/Descending sorting image in the Header elements

5.      Fix GridView height when the number of rows < the page size

6.      Built-in Filter Textbox

7.      Built-in Checkbox per row and per whole GridView

In addition we have created three simple buttons that can be enabled to have a confirmation client-side message or to function normally.

·         Confirm Button

·         Confirm Image Button

·         Confirm Link Button

The Basics

The extended GridView control inherits and this extends the GridView control that is part of the new set of controls that ship with ASP.NET 2.0.

The following code listing shows the header of the extended GridView control.

Listing 1

namespace CustomControls
{
    namespace Grid
    {
        [ToolboxData("<{0}:xGrid runat=server></{0}:xGrid>")]
        public partial class xGrid : GridView
        {

To use this control, simply drag it from the Visual Studio 2005 Toolbox after you have added it to the Toolbox.  Adding it to the Visual Studio 2005 Toolbox is not in the scope of this article.

A simple usage of the extended GridView control is as follows:

Listing 2

<xGrid:xGrid ID="XGrid1" runat="server"  AutoGenerateColumns="False" />
Single Row Click

This is the first new feature added to the GridView control.  You are now able, with just a single mouse click on a row, to post back and process a request.  You might think of implementing a master/detail using this single row click feature.  A new RowClick event has been added to the GridView that you can implement to process the single row click.

Related properties to this feature are:

·         EnableRowClick: This property can be either true or false.  By default it is false.

·         MouseOverColor: This property specifies the mouse over color on a row when the EnableRowClick is set to true.  It is shared between Single Row Click and Double Row Click features.

Figure 1 shows a row clicked (then selected) and a simple line stating which row was clicked.

Figure 1

 

You can handle the RowClick event and include any code to process when a single row click occurs.

Listing 3

protected void XGrid1_RowClick(object sender, RowClickEventArgs e)
{
  Response.Write("You clicked row: " + e.GridViewRow.RowIndex);
}

The RowClickEventArgs extends the default EventArgs class and adds a new property called GridViewRow that gives you full access to the row that has been clicked.

Double Row Click

This is the second new feature added to the GridView control.  You are now able, with just a double mouse click on a row, to post back and process a request.  You might think of putting the current row double clicked in Edit mode as a simple usage of this feature.  A new RowDoubleClick event has been added to the GridView that you can implement to process the double row click.

Related properties to this feature are:

·         EnableRowDoubleClick: This property can be either true or false; by default it is false.

·         MouseOverColor: This property specifies the mouse over color on a row when the EnableRowDoubleClick is set to true.  It is shared between Single Row Click and Double Row Click features.

Figure 2 shows a row double clicked (then selected) and a simple line stating which row was double clicked.

Figure 2

 

You can handle the RowDoubleClick event and include any code to process when a double row click occurs.

Listing 4

protected void XGrid1_RowDoubleClick(object sender, RowDoubleClickEventArgs e)
{
  Response.Write("You double clicked row: " + e.GridViewRow.RowIndex);
}

The RowDoubleClickEventArgs extends the default EventArgs class and adds a new property called GridViewRow that gives you full access to the row that has been double clicked.

ContextMenu row-based

During our research that spread over a month and a half, we could not find any GridView ContextMenu enabled!  This is the first built-in enabled GridView ContextMenu!

We have used the context menu developed by Dino Esposito that was published in the MSDN magazine.  A link to that article is listed below in the resource section.

That context menu was developed mainly for ASP.NET 1.1.  We have created a new project in ASP.NET 2.0 and copied the same code with some changes.  In one change OnClickClick property has been added to each context menu item so that developers can attach some client side code that runs before posting back to the server.

The client side code, mainly the JavaScript used by the context menu, is now included as a resource according to the techniques used in ASP.NET 2.0.

The context menu is now an ASP.NET 2.0 project.  It has been integrated within each row in the extended GridView control, so that when you right click on a row, you will be able to have access to the right-clicked row.  The extended GridView control now has a new property called RightClickRow that returns the current row that has been right-clicked to show the context menu.

Related properties to this feature are:

·         ContextMenuID: The GridView is context menu enabled when this property is set to the ID of a context menu placed on the ASPX page.

·         RightClickedRow: This property returns the GridViewRow where the right click was applied to show the context menu.  Any option you choose from the context menu will be applied on the current row where you have applied a mouse right click.

Figure 3 shows a context menu when a mouse right click was applied on a row.

Figure 3

 

The context menu popped up when a mouse right click was applied on the row.  The current context menu shows 3 different options.

Add a new Row: When clicked, a new entry row will be shown in the footer of the GridView control.  This is shown in Figure 4.

Delete Row: Allows you to delete the current right-clicked row.

Edit Row: Allows you to set the current right-clicked row in the edit mode.

Figure 4 that shows the GridView control in Insert mode when the “Add a new Row” option from the context menu was chosen.

Figure 4

Notice that the Context menu can be bound in several ways.

·         You can manually add new ContextMenuItem objects through the ContextMenuItems property of the context menu.

·         You can gather data from a database, loop through them and finally add them to the ContextMenuItems property of the context menu.

·         Also, you can load an XML file.

The following are the steps required to enable Context Menu on the GridView control.

·         Add an instance of the ContextMenu control on the ASP.NET page.

·         Add an event handler for the items clicked inside the ContextMenu.

·         Load ContextMenu with ContextMenuItems.

Configure the GridView control’s ContextMenuID with the ID of the context menu added.

You can start as follows:

Listing 5

<ctMenu:ContextMenu ID="ContextMenu1"
 runat="server" BackColor="#99CCCC"
 ForeColor="Maroon" OnItemCommand="ContextMenu1_ItemCommand"
 RolloverColor="#009999" />

The above code listing shows a ContextMenu having an ID of ContextMenu1 and a handler for the menu items which is the OnItemCommand.  This handler will be fired once the user chooses an option from the ContextMenu.

The event handler can be something like the following.

Listing 6

protected void ContextMenu1_ItemCommand(object sender, CommandEventArgs e)
{
  // Use the RightClickedRow property which is a GridViewRow to know
  // which row was right-clicked
  int rowIndex = this.XGrid1.RightClickedRow.RowIndex;
 
  switch (e.CommandName)
  {
    case "Add":
      this.XGrid1.ChangeInsertMode(true);
      break;
    case "Edit":
      this.XGrid1.EditIndex = rowIndex;
      break;
    case "Delete":
      DeleteGridViewRow(rowIndex);
      break;
    default:
      break;
  }
}

In case the user chooses “Add a new Row,” then we are setting the GridView in an insert mode using the built-in new method, ChangeInsertMode.  This flips the GridView between Insert and normal modes.  To be able to allow the GridView to insert new rows, you need to set up the form controls used to gather data from users in the FooterTemplate of each Row.

In case the user chooses “Edit Row,” we are setting the GridView’s EditIndex so that the currently right-clicked row is in now edit mode.

When the user chooses “Delete Row,” we are calling a method that handles deleting from the GridView.

As aforementioned, we need to set the ContextMenuID property of the GridView to “ContextMenu1” in order to enable ContextMenu on the GridView.  A sample GridView is shown below.

Listing 7

        <xGrid:xGrid ID="XGrid1"
 runat="server" AllowPaging="True"
 AutoGenerateColumns="False" DataKeyNames="CustomerID"
 ContextMenuID="ContextMenu1">
            <Columns>
                <asp:TemplateField HeaderText="Manage Row">
                    <edititemtemplate>
                        <asp:LinkButton
 text="Update" runat="server" id="lnkUpdate"
 CommandName="Update" CommandArgument='<%
 Bind("CustomerID") %>' />&nbsp;&nbsp;
                        <asp:LinkButton
 text="Cancel" runat="server" id="lnkCancel"
 CommandName="Cancel" />
                    
</edititemtemplate>
                    <footertemplate>
                        <confirmControl:ConfirmLinkButton ID="lnkAdd" runat="server"
 Text="Add" MessageText="Are you sure you want to add this
 record?" OnClick="btnAdd_Click" />
                        <asp:LinkButton
 id="lnkCancelAdd" runat="server" text="Cancel"
 OnClick="btnCancel_Click" />
                    
</footertemplate>
                    <itemtemplate>
                        <asp:LinkButton
 id="lnkEdit" runat="server" CommandArgument='<%
 Bind("CustomerID") %>' CommandName="Edit"
 text="Edit" __designer:wfdid="w1"></asp:LinkButton>&nbsp;&nbsp;
 <confirmControl:ConfirmLinkButton id="lnkDelete"
 runat="server" CommandArgument='<% Bind("CustomerID")
 %>' CommandName="Delete" MessageText="Are you sure you want
 to delete this record?" Text="Delete"></confirmControl:ConfirmLinkButton> 
                    
</itemtemplate>
                </asp:TemplateField></Columns>

An example on how to load the ContextMenu from an XML file is shown in the listing below.

Listing 8

private void PopulateContextMenu()
{
  XmlReaderSettings settings = new XmlReaderSettings();
  string contextmenuxml = Path.Combine(Request.PhysicalApplicationPath,
    "contextmenu.xml");
 
  NameTable nameTable = new NameTable();
  object contextMenuItem = nameTable.Add("contextmenuitem");
 
  settings.NameTable = nameTable;
 
  using(XmlReader reader = XmlReader.Create(contextmenuxml, settings))
  {
    while (reader.Read())
    {
      // Read a single ContextMenuItem
      if ((reader.NodeType == XmlNodeType.Element) && (contextMenuItem.Equals
        (reader.LocalName)))
      {
        XmlReader subTree = reader.ReadSubtree();
        ContextMenuItem menuItem = new ContextMenuItem();
 
        // Get contents of a single ContextMenuItem
        while (subTree.Read())
        {
          if ((subTree.NodeType == XmlNodeType.Element) &&
            (subTree.LocalName.Equals("text")))
            menuItem.Text = subTree.ReadString();
 
          if ((subTree.NodeType == XmlNodeType.Element) &&
            (subTree.LocalName.Equals("commandname")))
            menuItem.CommandName = subTree.ReadString();
 
          if ((subTree.NodeType == XmlNodeType.Element) &&
            (subTree.LocalName.Equals("tooltip")))
            menuItem.Tooltip = subTree.ReadString();
 
          if ((subTree.NodeType == XmlNodeType.Element) &&
            (subTree.LocalName.Equals("onclientclick")))
            menuItem.OnClientClick = subTree.ReadString();
        }
 
        // Add item to ContextMenu
        this.ContextMenu1.ContextMenuItems.Add(menuItem);
      }
    }
  }
}

The XML file used is as follows.

Listing 9

<?xml version="1.0" encoding="utf-8" ?>
<contextmenu>
  <contextmenuitem>
    <text>Add a new Row</text>
    <commandname>Add</commandname>
    <tooltip>Add a new Row</tooltip>
    <onclientclick />
  </contextmenuitem>
  <contextmenuitem>
    <text>Delete Row</text>
    <commandname>Delete</commandname>
    <tooltip>Delete Row</tooltip>
    <onclientclick>return
 __ConfirmMessage('Are you sure you want to delete this
 row?');</onclientclick>
  </contextmenuitem>
  <contextmenuitem>
    <text>Edit Row</text>
    <commandname>Edit</commandname>
    <tooltip>Edit Row</tooltip>
    <onclientclick />
  </contextmenuitem>
</contextmenu>

Each ContextMenuItem contains the following fields to set.

·         Text: The text to be displayed in the ContextMenu.

·         CommandName: The name of the command to process, examples are "Edit," "Delete," "Add," or any other command name that you want to handle in the OnItemCommand event handler.

·         Tooltip: A tooltip to show on a ContextMenuItem.

·         OnClientClick: Any valid client side code to run before posting back to the server.

Ascending/Descending sorting image in the Header elements

This feature adds an ascending/descending image beside each element in the GridView header when it is configured for sorting.  When the GridView initially loads no images will be displayed; only when you click on a header element to sort to, a corresponding image is shown reflecting the current sort order.

Figure 5 shows an arrow beside a column that was clicked for sorting.

Figure 5

Related properties to this feature:

AscImage: This property specifies the path to the image used as an ascending image.

DescImage: This property specifies the path to the image used as a descending image.

Fix GridView height when number of rows < page size

Have you ever noticed that when the number of rows displayed in a GridView is less than the page number, the GridView shrinks in height?

Suppose you were in Page 1 of a GridView showing 10 records, then you moved to Page 2 where it displays only 5 records, you will notice that the GridView height shrunk to fit those 5 records.  This can be annoying!   Would not it be better to keep the GridView height the same no matter the number of records being displayed?

In Figure 6 you will see a GridView with only a few records and you will notice empty records are added automatically because the number of records shown is less than the GridView’s page size.

Figure 6

Notice the three empty records added just to maintain the GridView height.

This is a built-in feature so you would find any property in the extended GridView control to configure it.

Built-in Filter Textbox

This is the second most interesting feature after the ContextMenu feature.  You can type any text inside a Textbox added to the GridView control in a custom header above the normal header.

You type in some text and hit the enter key on your keyboard.  An event handler for the FilterCommand is provided for you to handle the filtering the way you want it.  You can base your filtering on the one column data or all columns depending on the logic you provide in the FilterCommand event handler.

Related properties to this feature are:

IsFiltered: This property can be either true or false.  By default it is false.  When set to true, a new custom header will automatically be added to the GridView to allow users to enter text to filter the GridView accordingly.

FilterStyle: This property allows you to specify a style for the newly added custom header.  You configure this property much the same as you would do to the SelectedRowStyle, RowStyle, HeaderStyle, etc.

CSSFilterbox: This property allows you to provide a CSS class for the Textbox used in the custom header.

SkinIDFilterbox: This property allows you to provide a SkinID to the Textbox used in the custom header.

Figure 7 shows a GridView control with a custom header and some text that we have used to filter the GridView’s data.

Figure 7

Notice that paging, filtering, editing, etc. all function normally without requiring any special handling from your side.

You can handle the FilterCommand event and include any code to filter the GridView on.

Listing 10

protected void XGrid1_FilterCommand(object sender, FilterCommandEventArgs e)
{
  if (!e.FilterExpression.Equals(""))
  {
    FilterBind(e.FilterExpression.ToString());
    //return;
  }
 
   // Serves both with/out filter
  this.XGrid1.DataBind();
}

The FilterCommandEventArgs extends the default EventArgs class and adds a new property called FilterExpression that gives you the text that has been typed by the user in the filter Textbox.

Built-in Checkbox per row, and per whole GridView

This feature adds a checkbox to every row in a GridView and a main checkbox in the GridView’s header.  When a checkbox is checked, the whole row is selected.  Moreover, when the checkbox in the GridView’s header is checked, all the rows in the current Page will be selected.

The selection process is done on the client side without a need to post back.

This feature is taken from Dino Esposito’s article in MSDN magazine that extends the GridView to add this single feature.  The same code was used without any changes.

A link to Dino Esposito’s article is given in the resource section at the end of this document.

Related properties to this feature are the following.

AutoGenerateCheckBoxColumn: This property can be either true or false; by default it is false. When set to true, a new Column will be added to the GridView control, including a checkbox used to select a row.

CheckBoxColumnIndex: This property allows you to specify the location of the checkbox column in the GridView control.

Figure 8 shows a GridView control that has the AutoGenerateCheckBoxColumn set to true and the CheckBoxColumnIndex set to 0.

Figure 8

One thing to mention, when either EnableRowClick or EnableRowDoubleClick are enabled, selecting a row will not reflect a complete SelectRowStyle due to the effect of the MouseOverColor.  Once we select a row and the mouse is out, the row’s background will be revert back to the GridView’s original row background color, but the ForeColor will be applied.

Confirm Buttons

We have included three different buttons: Confirm Button, Confirm Image Button and Confirm Link Button.  These are normal buttons with two main properties added to each.

EnableConfirmMsg: This property can either be true or false.  When set to false, the button will be used as a normal button.  When the value is true, a confirmation message will be shown on the client side before posting back to the server.

MessageText: This property specifies the text to be shown when the EnableConfirmMsg is set to true.

Some of these buttons were used in the GridView templates which you can find in the accompanying downloadable code with this article.

Downloads
Resources

To be able to add all the above mentioned features, we had to research the web for a number of articles and blog posts to give us a deeper understanding of the GridView control, to learn how we could manipulate the GridView control and to add some of the features mentioned above.

Here is a list of most of the resources that were researched prior to building this extended GridView.

Adding a Context Menu to ASP.NET Controls

Fredrik Normen’s Blog

Building a Full-Featured Custom DataGrid Control

Ivan Porto Carrero's Blog

David Hayden's Blog

CodeSnip: Confirming Row Deletion in a GridView

Extending the GridView Control

Extending the GridView's Sorting Capabilities

Matt Dotson’s .NET Tips & Tricks

Mads Kristensen’s Blog

Brock Allen’s Blog

Conclusion

We have presented the seven new features added to the extended GridView control.  The main features are the ContextMenu row-based and the Filter Textbox to filter GridView rows.

If there are any comments or problems with the current features please do not hesitate to contact us to solve them.

In addition, if any one is seriously willing to help in improving the current features and add new features, feel free to contact me to share the code with you so that we can work together to improve the GridView control.

You could definitely use this GridView control with an ATLAS UpdatePanel to see how effective it would be to have all those features together with ATLAS.

Big thanks to Scott Guthrie, Polita Paulus, Dino Esposito, Scott Mitchell, Teemu Keiski, and Badri Narayanan and everyone else who helped us deliver this work.

Special thanks to Wessam Zeidan and Alister Jones for their continuous nonstop support.

Hope you enjoyed the new GridView control.

Happy Dot Netting!!


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-26 1:46:13 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search