Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

DataGridNavigator

0.00/5 (No votes)
17 Apr 2004 5  
ASP.NET server control which renders DataGrid navigator.

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:

[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:

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:

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:

[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:

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):

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:

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

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