Click here to Skip to main content
15,881,092 members
Articles / Web Development / ASP.NET
Article

DataGridNavigator

Rate me:
Please Sign up or sign in to vote.
4.69/5 (25 votes)
17 Apr 20044 min read 135.2K   4K   74   14
ASP.NET server control which renders DataGrid navigator.

Image 1

Introduction

One of my most used ASP.NET control is DataGrid. Presenting data from tables is very easy and nice with only one exception - the page navigator. Showing only page numbers or only two links (to previous and next page) is insufficient for me, and completely inexplicable for my clients. So I decided to create DataGridNavigator Server Control, the main task of which is to generate the page navigator for DataGrid object. The navigator can have the following buttons:

  • to jump to the first / last page (text or image)
  • to jump to the previous / next page (text or image)
  • to jump to the page no. ... (text only :) )

The navigator control is rendered independently of the DataGrid control, and you can bind multiple navigators to one DataGrid.

The control, properties and editors

The control inherits from the WebControl class (in ASP.NET, the control can inherit directly or indirectly from either the Control or WebControl base class) and is rendered in the span HTML tag.

Some of the properties have been assigned specified editors, like System.Web.UI.Design.ImageUrlEditor (for the xxxButtonImageUrl properties). This editor shows "Select image" dialog window (the same which is used in the ImageUrl property of the HyperLink control). All we have to do is to set the property's EditorAttribute:

C#
[Category("Buttons"), 
 DefaultValue(""), 
 Description("First button's image URL."), 
 EditorAttribute(typeof(System.Web.UI.Design.ImageUrlEditor), 
 typeof(System.Drawing.Design.UITypeEditor))] 
public string FirstButtonImageUrl 
{
   get { object o = ViewState["FirstButtonImageUrl"]; 
         return (o==null) ? String.Empty : (string) o; }
   set { ViewState["FirstButtonImageUrl"] = value.Trim(); } 
} 

There's also a special editor for the DataGridName property, which shows a list of all DataGrid objects on the page. You can find the editor's implementation in the DataGridNavigatorEditor.cs file.

The SelectDataGrid editor class

All editor classes should derive from the UITypeEditor class. One of the methods you should implement is the GetEditStyle, which returns editor type:

  • DropDown - dropdown dialog
  • Modal - modal window
  • None - no UI.

For example:

C#
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
    return UITypeEditorEditStyle.DropDown;
}

The next method to implement is EditValue, in which the editor window/control is created. In the case of the dropdown editor, we can use the ListBox control. As you can see in the DataGridNavigatorEditor.cs file, I've created an abstract class ObjectListEditor which implements the base functionality for that kind of editors. The class has InsertItems method used to fill the list with items. The main editor is implemented in the SelectDataGrid class, which derives from the ObjectListEditor class. Here is the implementation of the InsertItems method:

C#
protected override void InsertItems(ListBox.ObjectCollection items, 
                                            ComponentCollection components)
{
   // iterate thru all page's components
   for (int i = 0; i < components.Count; i++)
      // check if component is the DataGrid.
      if (components[i] is System.Web.UI.WebControls.DataGrid)
         items.Add(((System.Web.UI.WebControls.DataGrid)components[i]).ID);
}

As you can see, there is an iteration loop through the page's components. Every DataGrid component is added into the list items collection. If, for some reason, you would like to add other components, just change the conditional test.

Page's components collection (the method's component argument) is provided by the ITypeDescriptorContext interface (precisely by the Container.Components property), as you can see in the EditValue method implementation (in the ObjectListEditor class).

To assign the editor to the property, just set the EditorAttribute:

C#
[Category("Data"),
 DefaultValue(""),
 Description("DataGrid name to which connect the control."),
 Editor(typeof(mavus74.net.Editors.SelectDataGrid), 
 typeof(System.Drawing.Design.UITypeEditor))]
public string DataGridName
{
   get { object o = ViewState["DataGridName"]; 
         return (o==null) ? String.Empty : (string) o; }
   set { ViewState["DataGridName"] = value.Trim(); }
} 

The PostBack event

The main control's event is Command, based on the CommandEventHandler, which is invoked by the button click.

If control uses PostBack events, it should implement the IPostBackEventHandler interface. The Command event property is implemented as follows:

C#
private static readonly object EventCommand = new object();
 
 
...
 
[Category("Action"),
 Description("OnCommand event")]
public event CommandEventHandler Command
{
   add { Events.AddHandler(EventCommand, value); }
   remove { Events.RemoveHandler(EventCommand, value); }
}

This implementation relies on the C# event property construct. Now, it's time to implement the IPostBackEventHandler.RaisePostBackEvent method. In this method, you have to decide which event was invoked (the eventArgument has the event name):

C#
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
   // check event, and raise OnCommand with appropriate arguments.
   switch (eventArgument)
   {
      case "FIRST": 
         OnCommand(new CommandEventArgs("FIRST", 0));
         return;
      case "PREV": 
         OnCommand(new CommandEventArgs("PREV", 
         (dgData.CurrentPageIndex == 0) ? 0 : dgData.CurrentPageIndex - 1));
         return;
      case "NEXT": 
         OnCommand(new CommandEventArgs("NEXT", 
         (dgData.CurrentPageIndex == dgData.PageCount-1) ? dgData.PageCount-1 : 
         dgData.CurrentPageIndex + 1)); 
         return;
      case "LAST": 
         OnCommand(new CommandEventArgs("LAST", dgData.PageCount - 1));
         return;
   }
 
   if (eventArgument.StartsWith("PAGE_"))
   {
     int i = Convert.ToInt32( eventArgument.Remove(0, 5));
     OnCommand(new CommandEventArgs("PAGE", i));
   }
}

The OnCommand implementation:

C#
protected virtual void OnCommand(CommandEventArgs e)
{
   CommandEventHandler clickHandler = (CommandEventHandler)Events[EventCommand];
   if (clickHandler != null) clickHandler(this, e);
}

And the main point - rendering postback event code. The control renders a group of HTML links with post back event. The code is generated by the Page.GetPostBackClientHyperlink method, which gets two parameters:

  • control - the server control which will process the postback
  • argument - the event's argument, which is passed to the RaisePostBackEvent method.
C#
writer.AddAttribute(HtmlTextWriterAttribute.Href, 
    Page.GetPostBackClientHyperlink(this, "FIRST"));

The GetPostBackClientHyperlink method calls the GetPostBackEventReferece and appends 'javascript: ' text at the beginning.

Using the control

First, you need to bind the control with DataGrid by the DataGridName property. You also need to implement the Command event, for example:

C#
private void DataGridNavigator1_Command(object sender, 
                 System.Web.UI.WebControls.CommandEventArgs e)
{
   // e.CommandArgument has new PageIndex
   dgDane.CurrentPageIndex = (int) e.CommandArgument;
   bindData();
}

You also can set button's text, images and CSS class (ButtonsCssClass property). If you don't specify button's ImageUrl, than text link is rendered. Otherwise, image button is rendered. By setting the ShowPageButtons, you can decide to render page numbers. PageButtonCount property decides how many links to render (value between 3 and 21).

Points of Interest

This control shows how to create a server control with post back events handler, assign the property editor and how to create easy property editor.

TO-DO

  • specialized event handler instead of the CommandEventHandler. This handler can provide 2 properties: the DataGrid control and PageNumber (now it's CommandArgument).
  • DisabledImageUrl - image used when the link is disabled.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralDisplay image on datagrid Pin
quocbao2-Mar-07 13:23
quocbao2-Mar-07 13:23 
GeneralFix When Placed on a WebUserControl. Pin
Asela Gunawardena6-Jun-06 1:47
Asela Gunawardena6-Jun-06 1:47 
Quite Nice but would like add few things here. The control dose not work when placed on a WebUserControl(.ascx). The problem is you are looking for the datagrid only on the page if the search is executed on the control it self then everthing would be fine with your control. so guys whos willing to place this on a WebUserControl simple replace the DataGrid property with the following.

private DataGrid dgData
{
get
{
if (DataGridName.Length == 0) throw new System.Web.HttpException(String.Format("{0}.DataGridName : property can't be null.", ID));
if (_dgData == null)
{
_dgData = (DataGrid)Page.FindControl(DataGridName);

if(_dgData == null)
_dgData = (DataGrid)this.FindControl(DataGridName);

if (_dgData == null) throw new System.Web.HttpException(String.Format("{0}.DataGridName : Couldn't find assigned object '{1}'.", ID, DataGridName));
}

if(_dgData.PageCount<2)
this.Visible = false;
else
this.Visible = true;
return _dgData;
}
}

cheers.
QuestionBug!! Pin
Muffadal18-Oct-05 21:36
Muffadal18-Oct-05 21:36 
GeneralNice ! Pin
Trance Junkie21-Jun-05 21:05
Trance Junkie21-Jun-05 21:05 
Generalunable to make it work Pin
D.Sridhar19-May-05 10:29
D.Sridhar19-May-05 10:29 
GeneralDefinitely good Pin
pinguit29-Sep-04 20:33
pinguit29-Sep-04 20:33 
GeneralJust can't get it to work Pin
Dan Wright28-Sep-04 15:41
Dan Wright28-Sep-04 15:41 
GeneralRe: Just can't get it to work Pin
javierdotnet26-Jan-05 0:59
javierdotnet26-Jan-05 0:59 
Generalhide unused controls Pin
Yannick Smits11-Jun-04 19:17
Yannick Smits11-Jun-04 19:17 
GeneralRe: hide unused controls Pin
Dav Zen11-Jul-06 0:33
Dav Zen11-Jul-06 0:33 
GeneralRe: hide unused controls Pin
Yannick Smits17-Jul-06 15:14
Yannick Smits17-Jul-06 15:14 
GeneralYou can use AspNetPager free paging control! Pin
Webdiyer10-Jun-04 14:43
Webdiyer10-Jun-04 14:43 
GeneralRe: You can use AspNetPager free paging control! Pin
Ashaman24-Feb-05 6:48
Ashaman24-Feb-05 6:48 
GeneralVery good! Pin
anson_dragon9-Jun-04 23:33
anson_dragon9-Jun-04 23:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.