Resizable GridView Column

Deysomnath
Posted by in ASP.NET category on for Beginner level | Views : 24909 red flag

This article will help us to implement resizable gridview column

There's four important points to remember about it all.

1.Based on how the code is written, the Grid that has resizable columns must be contained in some other element (in these examples I use a DIV) and that element must have a style set of "position: absolute;". You need this to size the black vertical bar that attaches to the mouse correctly when performing an actual resize.

2.Based on how the code is written, you can only perform resize operations on table header cells (TH tags). This simply feels like the right way to do it - you could make it TD tags instead, and be able resize the column for the entire height of the table if you wanted to.

3.The actual table must have a style set of "table-layout: fixed;" If you don't set this style, strange things happen (try it and see, it goes all loopy when you resize .

4.To save having to remember to put too many requirements in the implementation, the black vertical bar is created dynamically. It's important to leave the creation of this element until the page's onload event fires - if it runs before it finishes loading, you IE sometime throws an error trying to call document.body.appendChild() - it took us ages to debug this!
So, first lets start with some simple styles


.tablecontainer
{
position: absolute;
}

.mytable
{
table-layout: fixed;
}

.mytable TD, .mytable TH
{
border: solid 1px black;
width: 120px;
}

.mytable TH
{
background-color: #e0e0e0;
}


Java script code


/*

Table Resizing code

*/

/*
Global constants to store elements that may be resized but we
could probably place these into custom table attributes instead.
*/
var sResizableElement = "TH"; // This MUST be upper case
var iResizeThreshold = 8;
var iEdgeThreshold = 8;
var iSizeThreshold = 20;
var sVBarID = "VBar";

/*
Global variables to store position and distance moved but we
could probably place these into custom table attributes instead.
*/
var oResizeTarget = null;
var iStartX = null;
var iEndX = null;
var iSizeX = null;

/*
Helper Functions
*/

/*
Creates the VBar on document load
*/

function TableResize_CreateVBar()
{
// Returns a reference to the resizer VBar for the table
var objItem = document.getElementById(sVBarID);

// Check if the item doesn't yet exist
if (!objItem)
{
// and Create the item if necessary
objItem = document.createElement("SPAN");

// Setup the bar
objItem.id = sVBarID;
objItem.style.position = "absolute";
objItem.style.top = "0px";
objItem.style.left = "0px";
objItem.style.height = "0px";
objItem.style.width = "2px";
objItem.style.background = "silver";
objItem.style.borderLeft = "1px solid black";
objItem.style.display = "none";

// Add the bar to the document
document.body.appendChild(objItem);
}
}

window.attachEvent("onload", TableResize_CreateVBar);

/*
Returns a valid resizable element, even if it contains another element
which was actually clicked otherwise it returns the top body element.
*/
function TableResize_GetOwnerHeader(objReference)
{
var oElement = objReference;

while (oElement != null && oElement.tagName != null && oElement.tagName != "BODY")
{
if (oElement.tagName.toUpperCase() == sResizableElement)
{
return oElement;
}

oElement = oElement.parentElement;
}

// The TH wasn't found
return null;
}

/*
Find cell at column iCellIndex in the first row of the table
needed because you can only resize a column from the first row.
by using this, we can resize from any cell in the table if we want to.
*/
function TableResize_GetFirstColumnCell(objTable, iCellIndex)
{
var oHeaderCell = objTable.rows(0).cells(iCellIndex);

return oHeaderCell;
}

/*
Clean up - clears out the tracking information if we're not resizing.
*/
function TableResize_CleanUp()
{
// Void the Global variables and hide the resizer VBar.
var oVBar = document.getElementById(sVBarID);

if (oVBar)
{
oVBar.runtimeStyle.display = "none";
}

iEndX = null;
iSizeX = null;
iStartX = null;
oResizeTarget = null;
oAdjacentCell = null;

return true;
}

/*
Main Functions
*/

/*
MouseMove event.
On resizable table This checks if you are in an allowable 'resize start' position.
It also puts the vertical bar (visual feedback) directly under the mouse cursor.
The vertical bar may NOT be currently visible, that depnds on if you're resizing.
*/
function TableResize_OnMouseMove(objTable)
{
// Change cursor and store cursor position for resize indicator on column
var objTH = TableResize_GetOwnerHeader(event.srcElement);

if (!objTH)
return;

var oVBar = document.getElementById(sVBarID);

if (!oVBar)
return;

var oAdjacentCell = objTH.nextSibling;

// Show the resize cursor if we are within the edge threshold.
if ((event.offsetX >= (objTH.offsetWidth - iEdgeThreshold)) && (oAdjacentCell != null))
{
objTH.runtimeStyle.cursor = "e-resize";
}
else
{
if(objTH.style.cursor)
{
objTH.runtimeStyle.cursor = objTH.style.cursor;
}
else
{
objTH.runtimeStyle.cursor = "";
}
}

// We want to keep the right cursor if resizing and
// don't want resizing to select any text elements...
if (oVBar.runtimeStyle.display == "inline")
{
// We have to add the body.scrollLeft in case the table is wider than the view window
// where the table is entirely within the screen this value should be zero...
oVBar.runtimeStyle.left = window.event.clientX + document.body.scrollLeft;

document.selection.empty();
}

return true;
}

/*
MouseDown event.
This fills the globals with tracking information, and displays the
vertical bar. This is only done if you are allowed to start resizing.
*/
function TableResize_OnMouseDown(objTable)
{
// Record start point and show vertical bar resize indicator
var oTargetCell = event.srcElement;

if (!oTargetCell)
return;

var oVBar = document.getElementById(sVBarID);

if (!oVBar)
return;

if (oTargetCell.parentElement.tagName.toUpperCase() == sResizableElement)
{
oTargetCell = oTargetCell.parentElement;
}

var oHeaderCell = TableResize_GetFirstColumnCell(objTable, oTargetCell.cellIndex);

if ((oHeaderCell.tagName.toUpperCase() == sResizableElement) && (oTargetCell.runtimeStyle.cursor == "e-resize"))
{
iStartX = event.screenX;
oResizeTarget = oHeaderCell;

// Mark the table with the resize attribute and show the resizer VBar.
// We also capture all events on the table we are resizing because Internet
// Explorer sometimes forgets to bubble some events up.
// Now all events will be fired on the table we are resizing.
objTable.setAttribute("Resizing", "true");
objTable.setCapture();

// Set up the VBar for display

// We have to add the body.scrollLeft in case the table is wider than the view window
// where the table is entriely within the screen this value should be zero...
oVBar.runtimeStyle.left = window.event.clientX + document.body.scrollLeft;

oVBar.runtimeStyle.top = objTable.parentElement.offsetTop + objTable.offsetTop;;
oVBar.runtimeStyle.height = objTable.parentElement.clientHeight;
oVBar.runtimeStyle.display = "inline";
}

return true;
}

/*
MouseUp event.
This finishes the resize.
*/
function TableResize_OnMouseUp(objTable)
{
// Resize the column and its adjacent sibling if position and size are within threshold values
var oAdjacentCell = null;
var iAdjCellOldWidth = 0;
var iResizeOldWidth = 0;

if (iStartX != null && oResizeTarget != null)
{
iEndX = event.screenX;
iSizeX = iEndX - iStartX;

// Mark the table with the resize attribute for not resizing
objTable.setAttribute("Resizing", "false");

if ((oResizeTarget.offsetWidth + iSizeX) >= iSizeThreshold)
{
if (Math.abs(iSizeX) >= iResizeThreshold)
{
if (oResizeTarget.nextSibling != null)
{
oAdjacentCell = oResizeTarget.nextSibling;
iAdjCellOldWidth = (oAdjacentCell.offsetWidth);
}
else
{
oAdjacentCell = null;
}

iResizeOldWidth = (oResizeTarget.offsetWidth);
oResizeTarget.style.width = iResizeOldWidth + iSizeX;

if ((oAdjacentCell != null) && (oAdjacentCell.tagName.toUpperCase() == sResizableElement))
{
oAdjacentCell.style.width = (((iAdjCellOldWidth - iSizeX) >= iSizeThreshold)?(iAdjCellOldWidth - iSizeX):(oAdjacentCell.style.width = iSizeThreshold))
}
}
}
else
{
oResizeTarget.style.width = iSizeThreshold;
}
}

// Clean up the VBar and release event capture.
TableResize_CleanUp();
objTable.releaseCapture();

return true;
}


Asp.net Code


ID="GridView1"
runat="server"
CssClass="mytable"
AutoGenerateColumns="true"
onmousemove="TableResize_OnMouseMove(this);"
onmouseup="TableResize_OnMouseUp(this);"
onmousedown="TableResize_OnMouseDown(this);">



That's all there is to it. There's on function called on mouse down, one on mouse move, and one on mouse up. The resizing happens in the mouse up event.

I have take help from (http://blogs.crankygoblin.com/blogs/geoff.appleby/pages/50712.aspx)
this web site and change the code according to my requirment.


Note: Please remember, this only works in Internet Explorer. There's several good reasons why this doesn't work in Firefox (all to do with the client-side javascript) and these include window.attachEvent() and element.parentElement(). I haven't looked at making a Firefox version yet.
Page copy protected against web site content infringement by Copyscape

About the Author

Deysomnath
Full Name: Somnath Dey
Member Level:
Member Status: Member
Member Since: 4/29/2008 9:36:46 PM
Country: United States

http://somnathdey.blogspot.com/
As soon as the fear approaches near, attack and destroy it.

Login to vote for this post.

Comments or Responses

Posted by: Webmaster on: 7/20/2007
Good Articles for those who are looking for resizable GridView columns, Despite same topic have been covered at other places but this one is very clear and simple. Good Job DeySomnath, Keep it Up!!!

Login to post response

Comment using Facebook(Author doesn't get notification)