Search

Use of DataGrid ItemDataBound Event (C#)

1 views

Understanding the ItemDataBound Event

The ItemDataBound event in the ASP.NET DataGrid control fires whenever a row of data is bound to the grid. Think of it as a callback that hands you a snapshot of the row just before it appears on the page. The event handler receives two arguments: the source object – which is the grid itself – and a DataGridItemEventArgs instance. That instance contains a reference to the DataGridItem that is currently being processed, giving you access to the row’s cells, its data source object, and its type (header, footer, item, alternating item, etc.). Once the handler exits, that snapshot disappears; you must capture or store any values you need before the method ends.

Hooking the event is straightforward. In the markup of your .aspx page, add the OnItemDataBound attribute to the asp:DataGrid declaration and point it to the name of your method. For example:

Prompt
<asp:DataGrid id="dg" runat="server" OnItemDataBound="ItemDataBoundHandler" ShowFooter="True"></asp:DataGrid></p>

When the page renders, the grid starts binding each row from its data source. As soon as a row is ready, the framework calls your ItemDataBoundHandler method. Inside that method you can inspect the row type, modify its appearance, alter cell values, or perform calculations that depend on the data in that row.

Because ItemDataBound is triggered for every row - including the header, footer, and separators - it’s a powerful place to implement row‑level logic. Common use cases include:

  • Formatting cells based on values (e.g., turning negative numbers red).
  • Aggregating totals or averages for a column and displaying them in the footer.
  • Adding dynamic controls to a cell.
  • Applying conditional CSS classes to alternate rows.

    When you need to know whether the current item is a regular data row or a special row, you use the ItemType property of the DataGridItem. The ListItemType enumeration lists all possible types: Header, Footer, Item, AlternatingItem, Separator, Pager, etc. A typical guard looks like:

    Prompt
    if (e.Item.ItemType == ListItemType.Footer) {</p> <p> // footer logic here</p> <p>}</p>

    Remember that ItemDataBound fires before the control renders to the browser, so any changes you make will be reflected in the final HTML. If you need to persist data across postbacks, store it in a session variable, hidden field, or a static variable, because the event’s context vanishes after execution.

    Performance considerations are minimal for most applications because the event executes quickly and only once per row. However, if your grid contains thousands of rows, keep your logic lean; heavy operations inside the handler can slow down rendering. In such scenarios, consider pre‑processing data in the code-behind or using a data view that already includes aggregates.

    In summary, the ItemDataBound event gives you a window into the binding process, letting you shape the final table on a per‑row basis. Mastering this event unlocks a range of dynamic behaviors that make your DataGrid both functional and visually appealing.

    Practical Example: Summing a Column in a DataGrid

    Let’s walk through a concrete scenario: calculating the total of a price column and showing that total in the grid’s footer. This example illustrates how to set up a data source, bind it to a DataGrid, and use ItemDataBound to accumulate values on the fly.

    First, create a DataTable that mimics a simple product catalog. We’ll define two columns: item and price. In the page’s code-behind, populate the table with a few sample rows. Notice that the table is declared as a protected field so that it can be reused across postbacks if necessary.

    Prompt
    protected DataTable dt = new DataTable("itemprice");</p> <p>dt.Columns.Add("item", typeof(string));</p> <p>dt.Columns.Add("price", typeof(float));</p> <p>DataRow dr;</p> <p>dr = dt.NewRow();</p> <p>dr["item"] = "pen";</p> <p>dr["price"] = 3.5f;</p> <p>dt.Rows.Add(dr);</p> <p>dr = dt.NewRow();</p> <p>dr["item"] = "camera";</p> <p>dr["price"] = 10.8f;</p> <p>dt.Rows.Add(dr);</p> <p>dr = dt.NewRow();</p> <p>dr["item"] = "coffee maker";</p> <p>dr["price"] = 40.2f;</p> <p>dt.Rows.Add(dr);</p> <p>// Bind the table to the grid</p> <p>dg.DataSource = dt.DefaultView;</p> <p>dg.DataBind();</p>

    When the grid renders, each row will show the item name and its price. To enable the footer, set the ShowFooter property to true in the markup.

    The core of the example lies in the event handler. Declare a class‑level variable to hold the running total, initialize it to zero, and increment it each time a data row is processed. When the footer row arrives, place the accumulated total into its cell.

    Prompt
    float total = 0f;</p> <p>protected void ItemDataBoundHandler(object sender, DataGridItemEventArgs e)</p> <p>{</p> <p> // Skip header and footer rows</p> <p> if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)</p> <p> {</p> <p> // Add the price from the second cell (index 1)</p> <p> total += float.Parse(e.Item.Cells[1].Text);</p> <p> e.Item.ForeColor = System.Drawing.Color.Blue; // optional styling</p> <p> }</p> <p> else if (e.Item.ItemType == ListItemType.Footer)</p> <p> {</p> <p> // Label the first cell and display the total in the second</p> <p> e.Item.Cells[0].Text = "Total";</p> <p> e.Item.Cells[1].Text = total.ToString("F2");</p> <p> }</p> <p>}</p>

    Notice how the handler uses ListItemType to differentiate between regular data rows, the header, and the footer. Only regular rows contribute to the total. The footer receives the final value, formatted to two decimal places for clarity. Styling the row in blue demonstrates how you can alter appearance on the fly.

    When this code runs, the rendered table looks like this: a list of items, each priced individually, followed by a footer row labeled “Total” that displays the sum of all prices. The total calculation happens entirely in the server, so the client receives a ready‑to‑display table.

    Why is this approach preferable to calculating the sum in a separate query or after binding? Because it eliminates the need for an additional pass over the data source. The ItemDataBound event already gives you the data in context, so you can aggregate on the fly without duplicating work. Additionally, if the grid supports paging, the handler automatically adapts: each page shows its own subtotal in the footer, which can be useful for user readability.

    For larger data sets or more complex calculations, you might store intermediate totals in session or view state and combine them after the grid renders. However, for most use cases, the simple pattern shown above is efficient and easy to maintain.

    Feel free to adapt this pattern for other types of aggregation - counts, averages, percentages - by tweaking the logic inside the ItemDataBound handler. The event’s flexibility makes it a go-to tool for dynamic grid customization.

    Reference: MSDN Library – DataGridItemEventArgs (January 2004)

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles