Tuesday, June 17, 2008

Custom control for resizing, tabing,soritng and how to use


This document contain the details of how to create custom control of grid view.
This Custom control contain the functionality for page level programmer

a) Sorting by clicking on header of grid view

b) Navigate to other page with Query String of cell text.

c)Show message “There are too many records to sort – please add more criteria” or something like if grid contains more recodes Max Record property.

d) Resizing columns of grid by dragging vertical line on header tab.

e)Tabbing moves from field to field, first left to right then down.
a)Many portion of dll is currently hard coded like tabbing index, navigation link but we can easily assigns it with property as we already take max records property.

b) No designer codes for control.

c)No visible description for page level programmer about property of controls.

Paddings work:-

Here we should completable our grid to expend its width on double click on page.

How to use:-

A simple use of control is give in B part of this document . Still we have to use Ajax for dragging the headers. Its worked fine and complete Javascript with relevant and technical comments. Has been written .

Part A

using System;
using System.Web;
using System.Web.UI;
using System.Drawing;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;

namespace searchControl

public class SortedGridContrl : Control, INamingContainer

/// The Control class is the base class for all ASP.NET server controls.

///INamingContainer is a marker interface without method. When a control inherits with INamingContainer,
///the ASP.NET page framework creates a new naming scope under that control,this ensur us that the child
///controls have unique names.

///About our approch of create sorted gridView Control :-
/// I add a property MaxReocrd which we can set for a message display for max records on
/// If the grid is too large (e.g. if it has so many records that sorting it will kill the server),
/// user gets a message when they try to sort that says “There are too many records to sort –
/// please add more criteria” or something like that.
/// This is Example custom control with possibility of enhancement. connection string as property
/// suitable name if we want to fill dataset every time from dataset.if we have to use itemtemplate etc.

/// How to use :-
/// Add reff of dll and choose it as a tool. and drag drop on page from tool box.
/// on CS page :-
/// page load :- SortedGridContrl1.DataSetSource = dst;
/// and nothing code for soting, only click the header.
/// On:- aspx page
/// ]cc1:SortedGridContrl ID="SortedGridContrl1" runat="server" MaxReocrd=25 ]

#region property and variables

private static Int16 cellIndex =99; /// Used for tabing in GridCell we set here heigher tab index for
/// GridView cell which will not distrub the tabindex of conrols page
/// In future we will suppy it with property.
private int RowIdex; /// Used for tabing in GridCell

private DataSet _dstforSorting = new DataSet();
private DataView _dv = new DataView();
private DataTable _dt = new DataTable();
private int? _MaxReocrd = null;
private DataSet _DataSetSource = new DataSet();

public int MaxReocrd

set { _MaxReocrd = value; }

/// ]summary]
/// Using this viewstate we save a DATABASE round for fill dataset.
/// ]/summary]
public DataSet DataSetSource

ViewState["ViewStateDst"] = value;
_dstforSorting = (DataSet)ViewState["ViewStateDst"];

private Label lblIfRowMoreThanLimit = new Label();

private GridView GV = new GridView();

#endregion property and variables

#region Create design view of control
protected override void CreateChildControls()///Called by the ASP.NET page framework to notify server controls
/// that use composition-based implementation to create any child
/// controls they contain in preparation for posting back or
/// rendering

#region gridView
GV.ID = "ZimsPoc";

GV.EnableViewState = true;
GV.AllowSorting = true;
GV.ShowHeader = true;
GV.AutoGenerateColumns = true;

GV.AllowSorting = true;

GV.Sorting += new GridViewSortEventHandler(this.GV_Sorting);
// GV.RowDataBound += new GridViewRowEventHandler(this.GV_RowDataBound);
GV.RowDataBound += new GridViewRowEventHandler(this.GV_RowDataBound);

/// The Sorting event is raised when the hyperlink to sort a column is clicked, but before the GridView
/// control handles the sort operation. This allows you to provide an event-handling method that performs
/// a custom routine

GV.DataSource = (DataSet)ViewState["ViewStateDst"];


#endregion gridView

#endregion Create design view of control

/// ]summary]
/// handling GridViewSortEventHandler . instance of the delegate to the event. And pass
/// GridViewSortEventArgs as agrument in sortedDataView function where sorting acctually taking place.
/// ]/summary]
/// ]param name="sender"]GridViewGV]/param]
/// ]param name="e"] GridViewSortEventHandler]/param]
protected virtual void GV_Sorting(Object sender, GridViewSortEventArgs e)
GV.DataSource = sortedDataView(e.SortExpression);



/// ]summary]
/// handling GridViewRowDataBoundHandler.instance of the delegate to the event.
/// ]/summary]
/// ]param name="sender"]Object sender]/param]
/// ]param name="e"]GridViewRowEventArgs]/param]
void GV_RowDataBound(Object sender, GridViewRowEventArgs e)

if (e.Row.RowType == DataControlRowType.DataRow)

///Looping for Add Tabing functionality i GridView and link is provided for
///navigate to new page. which will geting by page level user as a property
///of custom control.
#region Tabing

for (RowIdex = 0; RowIdex ] e.Row.Cells.Count; RowIdex = RowIdex + 1)
if (RowIdex ] 0)
e.Row.Cells[RowIdex].Text = "]a href='http://www.google.com?id=" + e.Row.Cells[RowIdex].Text + "' target=blank]" + e.Row.Cells[RowIdex].Text + "]/a]";

e.Row.Cells[RowIdex].TabIndex = cellIndex;
cellIndex += 1;
#endregion Tabing


/// ]summary]
/// Performing sorting of dataSet.
/// ]/summary]
/// ]param name="sortExp"]string sortExpression]/param]
/// ]returns]DataView]/returns]
private DataView sortedDataView(string sortExp)
_dstforSorting = (DataSet)ViewState["ViewStateDst"];
_dt = _dstforSorting.Tables[0];
_dv = _dstforSorting.Tables[0].DefaultView;
_dv.Sort = sortExp;

return _dv;
/// ]summary]
/// If the grid is too large
/// (e.g. if it has so many records that sorting it will kill the server),
/// user gets a message when they try to sort that says “There are too many records to sort
/// – please add more criteria” or something like that.
/// ]/summary]
private void MessageforMaxRecords()
if (_MaxReocrd != null)

if (_dstforSorting.Tables[0].Rows.Count ] _MaxReocrd)

lblIfRowMoreThanLimit.Text = "There are too many records to sort ]br/] – please add more criteria.";
Controls.Add(new LiteralControl("]br/]"));




Part B
Html Part :

]%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %]

]%@ Register Assembly="SortedGridComponenet" Namespace="searchControl" TagPrefix="cc1" %]

]!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"]
]html xmlns="http://www.w3.org/1999/xhtml"]
]head id="head" runat="server"]


]!-- set css for table --]

]style type="text/css"]
table { table-layout: fixed; width:700; }
td { word-wrap: break-word; text-overflow:ellipsis; overflow:hidden; white-space:nowrap; }

]form id="form" runat="server"]
]asp:ScriptManager runat="server" /]

]div style="width: 95%;"]
]b] how to use ]/b]]br /]]br /]

1) Drags Lines between headers columns
]br /]]br /]
Steps to implement.
]br /]]br /]
a) Add reff of sortedcustom control gridview dll.
]br /]
b) Add [ asp:ScriptManager ID="ScriptManager1" runat="server" /]
]br /]]br /]
c) put our control between updatePanel ]br /]
[asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"]
[cc1:SortedGridContrl ID="SortedGridContrl2" runat="server"]

]br /]]br /]

d) Add javaScript which written follows
]br /]]br /]

e)Don't forget add above style after title
[style type="text/css"]
table { table-layout: fixed; width:700px; }
td { word-wrap: break-word; text-overflow:ellipsis; overflow:hidden; white-space:nowrap; }
]br /]
f)add on little code in sortedgridview custom conttrol GV.ID="zimspoc" or alter little bit

]br /]]br /]

]br /]
]asp:UpdatePanel runat="server" UpdateMode="Conditional"]

]cc1:SortedGridContrl ID="SortedGridContrl1" runat="server"]


]script type="text/javascript"]

// true when a header is currently being resized
var _isResizing;
// a reference to the header column that is being resized
var _element;
// an array of all of the tables header cells
var _ths;

function pageLoad(args){

// get all of the th elements from the gridview

if($get('ZimsPoc') == null) // it is ID + _ + Zimspoc it is true after post back

_ths = $get('SortedGridContrl1_ZimsPoc').getElementsByTagName('th');

if($get('ZimsPoc') != null) // it is true first time on load
_ths = $get('ZimsPoc').getElementsByTagName('th');

// if the grid has at least one th element
if(_ths.length ] 1){

for(i = 0; i ] _ths.length; i++){
// determine the widths
_ths[i].style.width = Sys.UI.DomElement.getBounds(_ths[i]).width + 'px';

// attach the mousemove and mousedown events
if(i ] _ths.length - 1){
$addHandler(_ths[i], 'mousemove', _onMouseMove);
$addHandler(_ths[i], 'mousedown', _onMouseDown);

// add a global mouseup handler
$addHandler(document, 'mouseup', _onMouseUp);
// add a global selectstart handler
$addHandler(document, 'selectstart', _onSelectStart);

function _onMouseMove(args){

// determine the new width of the header
var bounds = Sys.UI.DomElement.getBounds(_element);
var width = args.clientX - bounds.x;

// we set the minimum width to 1 px, so make
// sure it is at least this before bothering to
// calculate the new width
if(width ] 1){

// get the next th element so we can adjust its size as well
var nextColumn = _element.nextSibling;
var nextColumnWidth;
if(width ] _toNumber(_element.style.width)){
// make the next column bigger
nextColumnWidth = _toNumber(nextColumn.style.width) + _toNumber(_element.style.width) - width;
else if(width ] _toNumber(_element.style.width)){
// make the next column smaller
nextColumnWidth = _toNumber(nextColumn.style.width) - (width - _toNumber(_element.style.width));

// we also don't want to shrink this width to less than one pixel,
// so make sure of this before resizing ...
if(nextColumnWidth ] 1){
_element.style.width = width + 'px';
nextColumn.style.width = nextColumnWidth + 'px';
// get the bounds of the element. If the mouse cursor is within
// 2px of the border, display the e-cursor -] cursor:e-resize
var bounds = Sys.UI.DomElement.getBounds(args.target);
if(Math.abs((bounds.x + bounds.width) - (args.clientX)) ]= 2) {
args.target.style.cursor = 'e-resize';
args.target.style.cursor = '';

function _onMouseDown(args){
// if the user clicks the mouse button while
// the cursor is in the resize position, it means
// they want to start resizing. Set _isResizing to true
// and grab the th element that is being resized
if(args.target.style.cursor == 'e-resize') {
_isResizing = true;
_element = args.target;

function _onMouseUp(args){
// the user let go of the mouse - so
// they are done resizing the header. Reset
// everything back

// set back to default values
_isResizing = false;
_element = null;

// make sure the cursor is set back to default
for(i = 0; i ] _ths.length; i++){
_ths[i].style.cursor = '';

function _onSelectStart(args){
// Don't allow selection during drag
return false;

function _toNumber(m) {
// helper function to peel the px off of the widths
return new Number(m.replace('px', ''));



Code Behind Part:-

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
SqlConnection sq0lcon = new SqlConnection(@"Data Source=\ver2005;Initial Catalog=test_navdeep;User ID=navdeep;Password=navdeep");
DataSet dst = new DataSet();
SqlDataAdapter dadAuthors;
SqlCommand sqlcmd = new SqlCommand("Select * from Test1", sq0lcon);
dadAuthors = new SqlDataAdapter(sqlcmd);

dadAuthors.Fill(dst, "dst");

SortedGridContrl1.DataSetSource = dst;



No comments: