Click here to Skip to main content
15,867,568 members
Articles / Web Development / IIS
Article

DataGridHelper tool

Rate me:
Please Sign up or sign in to vote.
4.71/5 (27 votes)
21 Jul 2005CPOL8 min read 174.1K   4.2K   128   27
A utility class to ease adding CSS classes and confirmation dialogs to the ASP.NET DataGrid component.

Image 1Try it online

Sample image of the tool in action

Introduction

When using Visual Studio .NET to create ASP.NET pages, the Property Builder is a great tool for quickly customizing the functionality or coloring of the ASP.NET DataGrid control on a single page. However, I've sorely missed the ability to add CSS class names to the different element types (Header, Footer, Item, AlternatingItem, etc.) programmatically, so I could alter the look of all DataGrids in my solution's pages from a single CSS file. I've looked around on the web for a solution, but since I didn't find any - I've created my own. This little utility class also has a few other tricks up its sleeve.

DataGridHelper can:

  • add CSS class names to all rows, cells and buttons in a DataGrid. E.g. "Item_row", "Header_cell", "Button_Update", etc. (one line of code).
  • add attributes to all rows and/or cells in a DataGrid (one line of code).
  • add a JavaScript confirmation dialog to the buttons in a column of a DataGrid (one line of code).

V. 1.2 - IHttpModule implementation
For those of you who want to add CSS classes to your DataGrids without even a single line of code, the DataGridHelper class now implements the IHttpModule interface. This makes it possible to have all DataGrids automatically get the CSS classes added in your entire solution (by editing the web.config file) or in all solutions on the server (by editing the machine.config file).
See how to do this [here].

Using the code

I've created a little web project to show you how to use this utility class. Most of the methods are pretty straightforward, but adding CSS to the DataGrid has a little catch: you have to call this method before databinding the DataGrid.

The reason for this is that I haven't been able to find a way of getting to the Header, Footer, Pager, etc. rows in the DataGrid in any other way than by attaching to the ItemDataBound event of the DataGrid.

I tried enumerating through the DataGrid.Items, but that only gives access to the Item, AlternatingItem, SelectedItem and EditItem items.

Here are the core methods:

C#
//Adds CSS class names to cells, rows and buttons in a datagrid
public static void AddCssToDataGrid(DataGrid aGrid); //(updated in version 1.1)

//Adds an attribute to all cells in a DataGrid
public static void AddAttributesToCells(DataGrid theGrid, 
       string attributeKey, string attributeValue);

//Adds an attribute to all rows in a DataGrid
public static void AddAttributesToRows(DataGrid theGrid, 
       string attributeKey, string attributeValue);

//Adds a confirm javascript dialog to the buttons in a column of a DataGrid
public static void AddConfirm(DataGrid theGrid, 
                   int columnNumber, string question);

The sample project I've included follows the traditional pattern of many web projects:

  • Page_Load - Check to see if we have data in Session.
    • If not - load it from disk into session.
  • Events
    • If "Delete" was clicked - delete that row.
    • If "Load data" was clicked - reload the data.
  • PreRender
    • Databind and make last minute modifications.

For those of you unfamiliar with this approach, it will help you to know that ASP.NET pages are always processed in the same order.

  • Page_Load goes first, which means that this is a good place to make sure that data is loaded.
  • All events are processed next, this includes all postback events (button clicks, etc.) and is the time to delete, edit and add stuff.
  • PreRender runs last, and this is the time to present the data in its current state. In other words "databind".

To put this in another way: "Load data" - "Edit data" - "Show data".

The entire web project is not much of an application as such. It was solely created to display the DataGridHelper class' functionality.

Things to note:

  • I have an external CSS file "sample.css" with the styles "Item_cell", "AlternatingItem_cell", etc. This automatically colorizes the DataGrid after the CSS classes have been added to the cells and rows.
  • I have an external JavaScript file "scripts.js" with a little DHTML script that dynamically changes the CSS classes of HTML objects, so they present themselves differently visually, depending on their class.
  • To avoid having to include a database in the sample project, I created a typed dataset, loaded the database table into it, and wrote it to disk using the DataSet's WriteXml() method. This way I can (and do) reload the data into the DataSet using the ReadXml() method.
  • I have a DataGrid named dgPersons on the page. Using the Property Builder in Visual Studio, I have added a hidden first column (column 0) to this DataGrid containing the primary key of the rows in the DataTable. This way I can easily look up the corresponding row in the DataTable when a user clicks the Delete button in a row.

Image 3

The sample project's code

DataSet as a member variable

I have declared my typed dataset as a member level variable so I can access it from all methods:

C#
//the dataset containing the table with our persons
protected dsPersons persons;

Page_Load loads data

All that happens when the page loads is that data is loaded.

C#
private void Page_Load(object sender, System.EventArgs e)
{
    //load the data to display
    LoadData();
}

LoadData() method

Here is the LoadData method that is called from Page_Load:

C#
public void LoadData()
{
    //if we don't have any data in Session state
    if(Session["persons"] == null)
    {
        //find the full path to the xml file
        string path = Server.MapPath("persons.xml");
        //create a new, empty dataset
        persons = new dsPersons();
        //fill it with data from the file
        persons.ReadXml(path);
        //save it in Session state
        Session["persons"] = persons;
    }
    //in all cases, we can now retrieve 
    //the dataset from Session state
    persons = (dsPersons) Session["persons"];
}

...at this point we are sure to have a loaded dataset in the Session, so if this page view was caused by a click on a Delete button, then we can go ahead and mark that row as deleted in the DataTable:

Delete event finds and removes a person:

C#
private void dgPersons_DeleteCommand(object source, 
              System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
    //we find the id of this row 
    //by looking in the hidden first colum
    int id = int.Parse(e.Item.Cells[0].Text);
    //this person we look up in the Table,
    //and mark the row for deletion
    persons.person.FindByid(id).Delete();
}

If the user didn't click "Delete", but "Reload data", then this event would also occur at this time in the page's lifecycle, and we could load the data anew:

Reload data from file:

C#
private void btnReloadData_Click(object sender, System.EventArgs e)
{
    //empties the Session state of data
    Session["persons"] = null;
    //reloads the dataset from disk
    LoadData();
}

In any case - the PreRender event happens last, and this is the place where my utility class gets to work:

PreRender displays the data:

C#
// This method runs right before the page
// and all its controls are converted to HTML
// and sent to the client's browser.
// This is the place to databind,
// and therefore we do all the adding of 
// attributes, etc. here.
private void WebForm1_PreRender(object sender, System.EventArgs e)
{
    //if the checkbox is checked
    //then we add CSS class names
    //so the CSS file's contents get to work
    if (chkAddCSS.Checked)
        DataGridHelper.AddCssToDataGrid(dgPersons);
    
    //set the datagrid's datasource to the
    //table containing our people
    dgPersons.DataSource = persons.person;
    //bind the data
    dgPersons.DataBind();

    //if the user wants to add deleteconfirmation
    if(chkAddDeleteConfirmation.Checked)
    {
        //then we add a confirmation dialog to the
        //linkbutton in row 3.
        //Remember that we've hidden row zero 
        //that's why the Delete row is number three.
        DataGridHelper.AddConfirm(dgPersons, 3, 
              "Do you wish to delete this person?");
    }
    
    //if the user wants to add mouseovers
    if(chkAddJavascriptMouseovers.Checked)
    {
        //add the mouseover and mouseout attributes
        //and link them to to the javascript 
        //function "changeStyle()"
        DataGridHelper.AddAttributesToCells(dgPersons, 
                "onmouseover", "changeStyle(event);");
        DataGridHelper.AddAttributesToCells(dgPersons, 
                 "onmouseout", "changeStyle(event);");
        //using the event to make the javascript cross-browser
        //you can add any code you like with 
        //the "AddAttributesToCells" method.
    }
    
    //make sure all columns in the DataGrid 
    //are one third of the width
    DataGridHelper.AddAttributesToCells(dgPersons,"width", "33%");
}

Points of Interest

The JavaScript

You can use any of your own or other people's JavaScript code along with the DataGridHelper class. I've just included one of my more interesting JavaScript codes here, in case you could use the same functionality at some point in life. I switch the CSS class name of the cells in the table when the mouse moves over them.

Image 4

This is done instead of the altering color, size, etc. directly. By using this approach you are able to revert to the original state of the cell when your mouse leaves it, because I only append and remove the suffix "_hover" to the class name.

Because we have two alternating rowtypes "Item" and "AlternatingItem", we can't just reset the rows' or cells' background color to a predefined color, as this would make the rows appear alike after a mouseout.

Have a look and see if you like it.

Update: This is an improved version that uses cross-browser scripting to access the event model of either IE or FireFox.

JavaScript
<script language="javascript">
//////////////////////////////////////////////////
//        CHANGESTYLE - by Jakob Lund Krarup        //
//////////////////////////////////////////////////
/*This method will change the CSS class name
of an HTML item.
The name gets the text "_hover" appended 
when the mouse moves over the item,
and the name has the text "_hover" removed
from the class name when the mouse moves out again.

CROSSBROWSER:
Made this work with FireFox after reading:
http://www.oreillynet.com/pub/a/javascript/synd/2001/09/25/event_models.html?page=2
*/
function changeStyle(evt)
{
    //Crossbrowser - get the event as a parameter (FireFox)
    //or as the windows event (IE)
    var theEvent =  evt || window.event;
    //Crossbrowser - get the HTML element that fired this event
    //as either target (FireFox) or srcElement (IE)
    var theEventSource = theEvent.target || theEvent.srcElement;
                
    //according to the event type
    //...switch the CSS class of the element
    switch(theEvent.type)
    {
        //if the event that invoked this method
        //was a mouseover event
        case "mouseover" :
            //then we add "_hover" to the class name
            theEventSource.className  += "_hover";
            break;
                        
        //otherwise - if this was a mouseout event...
        case "mouseout"  : 
            //then we remove the "_hover" from the class name    
            theEventSource.className = 
                theEventSource.className.replace("_hover", "");
    }
}
</script>

This allows us to define CSS classes like this, that work with the cells of DataGrid:

HTML
.Item_cell {
    background-color: Cornflowerblue;}
    
.Item_cell_hover {
    background-color: red;
    font-weight:bold;
    color: White;}

Advanced - IHttpModule interface implementation (version 1.2)

This implementation makes it possible for the DataGridHelper class to attach CSS to all "outgoing" DataGrid controls in a web project without you having to write code for each of them. If you just want to use the DataGridHelper class and call the methods when needed, then just skip this last part. To make this work, you have to add the HttpModuleDataGridHelper.dll file to the BIN folder of your web application, and add the following lines to the </system.web> part of your web.config:

web.config addition

XML
<httpModules>
  <add name="DataGridHelperModule"
    type="AddCssToDataGridSample.DataGridHelper, HttpModuleDataGridHelper" />
 </httpModules>

In case you don't want to manually edit your web.config, just run this tool in your web application's folder. It will update your web.config file for you, and download the DataGridHelper.dll file from the Internet to the BIN folder. The next article I submit to The Code Project will be about this installer-tool, and how it was made.

(If you want to know more about coding HttpModules, I suggest you read this article.)

Ending note

I thoroughly enjoy the CodeProject newsletter each week. I am an avid reader and I hope my contribution has given something back to you, the community:)

Before you rush to the keyboard to let me know that I can just add a CSS class to my DataGrid and then define how the TD code or TR code should be styled using the ".datagrid td" code, I just want to let you know that I know ; ).

I just think it is easier to adjust any client scripting, CSS or DHTML if all cells and rows have a CSS class.

Kind regards - Jake (Jakob Lund Krarup).

History

  • 1.2
    • Added implementation of the IHttpModule interface to the DataGridHelper class. So in addition to working as before, you can now have the CSS classes added with no code : )
  • 1.1
    • As suggested by R.vd.B - I've changed the AddCssToDataGrid so it also adds CSS classes to the buttons in the DataGrid.
    • Scott (bisc0tti) noticed that when the CSS was added in FireFox, the delete confirmation didn't work. This hasn't got anything to do with the DataGridHelper class, but was a lack of cross-browser programming in the sample JavaScript I used.
    • The script has been updated to work cross-browser now : ).
    • Thanks Scott (and SirTrolle who made the connection to the CSS)! : )

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer UCN
Denmark Denmark
Happy coder - with an urge to learn and share learning. Proficient in juggling, calligraphy, balloon animals, and drawing.

I've been coding since 1990, where a friend introduced me to QBASIC. Since then I've been through Delphi, HTML, Javascript, ASP (classic), Java and am now completely and thoroughly in love with C# ; )

I love coding games (XNA/Monogame) and creating utility classes. I always strive to remove repetitive coding tasks from my development efforts by creating helperclasses or subclassing existing controls and classes.

I teach Systems Development at University College Nordjylland (UCN), Denmark.

Comments and Discussions

 
Generalthank u Pin
tareqGamal10-Aug-06 3:05
tareqGamal10-Aug-06 3:05 
GeneralRe: thank u Pin
Jakob Farian Krarup10-Aug-06 5:05
Jakob Farian Krarup10-Aug-06 5:05 
GeneralUnable to build Pin
Kokas19-Oct-05 23:17
Kokas19-Oct-05 23:17 
Generalvb.net Pin
rready10-Aug-05 4:40
rready10-Aug-05 4:40 
GeneralRe: vb.net Pin
Jakob Farian Krarup10-Aug-05 6:31
Jakob Farian Krarup10-Aug-05 6:31 
GeneralRe: vb.net Pin
rready10-Aug-05 9:39
rready10-Aug-05 9:39 
GeneralGood job Pin
Knight32025-Jul-05 20:31
Knight32025-Jul-05 20:31 
GeneralGreat Pin
Alessio.NET21-Jul-05 23:38
Alessio.NET21-Jul-05 23:38 
GeneralRe: Great Pin
Anonymous22-Jul-05 0:11
Anonymous22-Jul-05 0:11 
GeneralWell done! Pin
lovelydinasour00118-Jul-05 16:44
professionallovelydinasour00118-Jul-05 16:44 
GeneralRe: Well done! Pin
Jakob Farian Krarup18-Jul-05 22:42
Jakob Farian Krarup18-Jul-05 22:42 
You are most welcome! Big Grin | :-D

Thank you for your feedback!

Kind regards - Jakob

Three kinds of people in the world:
- Those who can count..
- Those who can't!
Generalstyling using aspx (not hardcoded) Pin
ernest_elias10-Jul-05 21:13
ernest_elias10-Jul-05 21:13 
Generalstyling using aspx (not hardcoded) - correction Pin
ernest_elias10-Jul-05 21:22
ernest_elias10-Jul-05 21:22 
GeneralRe: styling using aspx (not hardcoded) - correction Pin
Jakob Farian Krarup17-Jul-05 1:00
Jakob Farian Krarup17-Jul-05 1:00 
GeneralRe: styling using aspx (not hardcoded) - correction Pin
ernest_elias17-Jul-05 20:31
ernest_elias17-Jul-05 20:31 
GeneralRe: styling using aspx (not hardcoded) - correction Pin
Jakob Farian Krarup17-Jul-05 20:51
Jakob Farian Krarup17-Jul-05 20:51 
GeneralAnd how about the buttons .... Pin
R.vd.B22-Jun-05 19:47
R.vd.B22-Jun-05 19:47 
GeneralRe: And how about the buttons .... Pin
Jakob Farian Krarup23-Jun-05 5:46
Jakob Farian Krarup23-Jun-05 5:46 
GeneralRe: And how about the buttons .... Pin
R.vd.B27-Jun-05 1:59
R.vd.B27-Jun-05 1:59 
Generalcancel button on delete confirmation Pin
bisc0tti21-Jun-05 6:09
bisc0tti21-Jun-05 6:09 
GeneralRe: cancel button on delete confirmation Pin
Jakob Farian Krarup21-Jun-05 6:26
Jakob Farian Krarup21-Jun-05 6:26 
GeneralRe: cancel button on delete confirmation Pin
bisc0tti21-Jun-05 8:40
bisc0tti21-Jun-05 8:40 
GeneralRe: cancel button on delete confirmation Pin
Jakob Farian Krarup21-Jun-05 9:04
Jakob Farian Krarup21-Jun-05 9:04 
GeneralRe: cancel button on delete confirmation Pin
SirTrolle21-Jun-05 10:30
SirTrolle21-Jun-05 10:30 
GeneralUpdate event on data grid Pin
dvsr20-Jun-05 8:07
dvsr20-Jun-05 8:07 

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.