I see a lot of questions on the forums dealing with the formatting of data
displayed in the
DataGrid. People want to know how to
change the colors of a row, text or the value displayed based on some
condition. In this article I will demonstrate how to use two different
techniques to modify the output and formatting of your data. I will show
you how to use a helper function to change the data displayed. After
that, I will explain how to use the
OnItemDataBound
event of the
DataGrid
to modify the data and the formatting of the grid.
Setup
First, I set up my data file for this example. In this case it is a
simple XML file of contacts. Some of the requirements for my grid display
include:
-
Combining the first and last name
-
Changing the Manager field to read Manager if the value is a 1 or Employee if
the value is a 0
-
Changing the background color of any row that has a value of 1 in the Manager
field.
<?xml version="1.0" standalone="yes"?>
<Contacts>
<Contact>
<Email>myaddress@mycompany.com</Email>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Manager>0</Manager>
</Contact>
<Contact>
<Email>youraddress@yourcompany.com</Email>
<FirstName>Jane</FirstName>
<LastName>Doe</LastName>
<Manager>1</Manager>
</Contact>
<Contact>
<Email>fred@bedrock.com</Email>
<FirstName>Fred</FirstName>
<LastName>Flintstone</LastName>
<Manager>0</Manager>
</Contact>
<Contact>
<Email>barney@bedrock.com</Email>
<FirstName>Barney</FirstName>
<LastName>Rubble</LastName>
<Manager>0</Manager>
</Contact>
<Contact>
<Email>slate@bedrock.com</Email>
<FirstName>Mr</FirstName>
<LastName>Slate</LastName>
<Manager>1</Manager>
</Contact>
</Contacts>
Next I set up my grid. I wanted to combine the names into
one column in a First Name, Last Name format, so I used a
TemplateColumn. The other two columns are
simply bound to one field each so a
BoundColumn
suffices.
<asp:DataGrid id="dgContacts" runat="server" AutoGenerateColumns="False"
Width="370px">
<ItemStyle CssClass="item"></ItemStyle>
<HeaderStyle CssClass="heading"></HeaderStyle>
<Columns>
<asp:TemplateColumn HeaderText="Name">
<ItemTemplate>
<asp:Label runat="server"
Text= '<%# DataBinder.Eval(Container, "DataItem.FirstName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="Email" ReadOnly="True"
HeaderText="Email"></asp:BoundColumn>
<asp:BoundColumn DataField="Manager" ReadOnly="True"
HeaderText="Status">
<HeaderStyle
HorizontalAlign="Center"></HeaderStyle>
<ItemStyle
HorizontalAlign="Center"></ItemStyle>
</asp:BoundColumn>
</Columns>
</asp:DataGrid>
Which Method?
Now that the
data, the display requirements and the grid ready to
go I needed to decide which methods to use for displaying the data. Using
a helper function is an easy way to change the output of the data. In
order to change the format of the grid based on a condition the
ItemDataBound
event is the way to go. With those rules of thumb in mind, this
is how I decided to tackle things:
| Column |
Method |
Reasoning |
| Name |
Helper |
The output needs to simply combine the FirstName and LastName
fields. |
| Email |
None |
Nothing has to be changed. |
| Status |
ItemDataBound |
The background color of the row needs to be changed based on the
value in the Manager field. In addition, the display needs to be changed
to Manager or Employee based on the value in
the Manager Field. The second part could have been done easily in a
helper function, but since I'm already using the ItemDataBound event I decide
to do both actions in one place. |
The Helper Function
Setting up the helper function is simple. First I created the function
in the code behind. Note that the function scope is declared as
protected. This is necessary since the
function will be called from the ASPX page rather than the code behind.
Leaving the function
private
will cause an error when the page is parsed.
[C#]
protectedstring FormatFullName(object FirstName, object LastName)
{
// Combine the names to get the Last, First format.
return (string)LastName + ", " + (string)FirstName;
}
[VB]
ProtectedFunction FormatFullName(ByVal FirstName AsObject, ByVal LastName AsObject) AsString
' Combine the names to get the Last, First format.
ReturnCType(LastName, String) & ", " & CType(FirstName, String)
EndFunction
In order to call the function from the grid I changed the Text
value of the Label in the TemplateColumn.
<asp:Label
runat="server" Text='<%# FormatFullName(DataBinder.Eval(Container,
"DataItem.FirstName"), DataBinder.Eval(Container, "DataItem.LastName"))
%>'>
The ItemDataBound Event
Then, I moved on to the
ItemDataBound
event of the grid. One thing that you should keep in mind when
working with this event is that it is fired for each row that is
created in the DataGrid. This
includes Header and Footer rows! As a result, you must be
sure you're working with the correct type of row. This is done by
checking the
ItemType
property of the
Item
object. I can't tell you how many times I've encountered a run-time error
when trying to access a control that existed in a data row but did not exist in
the header row because of overlooking this step!
[C#]
protectedvoid dgContacts_ItemDataBound(object source, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
// Make sure that this is a data row and not a header or footer.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// Get the value of the manager field.
string isManager = (string)DataBinder.Eval(e.Item.DataItem, "Manager");
if (isManager == "1")
{
// Set the text and background color.
e.Item.Cells[2].Text = "Manager";
e.Item.BackColor = System.Drawing.Color.AliceBlue;
}
else
{
// Set the text only.
e.Item.Cells[2].Text = "Employee";
}
}
}
[VB]
PrivateSub dgContacts_ItemDataBound(ByVal sender AsObject, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles
dgContacts.ItemDataBound
' Make sure that this is a data row and not a header or footer.
If e.Item.ItemType = ListItemType.ItemOrElse e.Item.ItemType = ListItemType.AlternatingItem Then
' Get the value of the manager field.
Dim isManager AsString = CType(DataBinder.Eval(e.Item.DataItem, "Manager"), String)
If isManager = "1"Then
' Set the text and background color.
e.Item.Cells(2).Text = "Manager"
e.Item.BackColor = System.Drawing.Color.AliceBlue
Else
' Set the text only.
e.Item.Cells(2).Text = "Employee"
EndIf
EndIf
EndSub
Results
At last we come to the fun part, seeing what has been created! If I've
done everything correctly, I should get a simple grid with three columns. One
with the name of the contact formatted last name and first name. The next
has the email address and the last is the status column denoting whether the
person is a manager or an employee. Finally, any contact that is a manger
should have the background color of the row set to AliceBlue. Let's see
what I ended up with!

Summary
As you can see, there are different methods for changing the output and
formatting of the data in your DataGrid. The method you choose depends on
the actions that you need to perform or which method you prefer. Both are
very easy and when you use them, it will increase the usefulness of the
DataGrid control.