GridView RowDataBound Handler - Can't get data from row
I have a GridView with an anonymous type. I need to check the value in a cell and highlight that cell if a condition is met. The problem is, I always get an empty string when I try to pull data out of the row's cells. I have successfully highlighted all the cells and I have checked in the Visual Studio 2010 debugger and confirmed that the Row has data (the row's DataItem has the values I need). This is happening on a PostBack, I'm not sure if that's a problem or not.
Here is the code and solutions I've tried:
protected void grvValidCourses_RowDataBound(Object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.DataRow) {
String str = e.Row.Cells[6].Text.ToString(); // empty string
Label lbl = (Label) grvValidCourses.FindControl("lblEndDate"); // null
DataRowView rowView = (DataRowView)e.Row.DataItem; // exception about casting anonymous type
What's going on here? Why can't I get data from the cells?
Markup for GridView:
<asp:GridView ID="grvValidCourses" runat="server" Width="790px" OnRowCancelingEdit="grvValidCourses_RowCancelingEdit"
OnRowEditing="grvValidCourses_RowEditing" OnRowUpdating="grvValidCourses_RowUpdating" OnRowDeleting="grvValidCourses_RowDeleting"
AutoGenerateColumns="False" OnSelectedIndexChanged="grvValidCourses_SelectedIndexChanged"
OnRowDataBound="grvValidCourses_RowDataBound" >
<Columns>
<asp:CommandField ShowEditButton="True" EditText="Edit" UpdateText="Update |" />
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="lbnDelete" runat="server" CausesValidation="False" CommandName="Delete"
Text='<%# (Eval("active") == null ? "Delete" : ((Eval("active").ToString() == "0" ? "Restore" : "Delete"))) %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowSelectButton="True" SelectText="Details" />
<asp:TemplateField HeaderText="Training Name" SortExpression="coursename">
<EditItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("coursename") %>'></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("coursename") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ttNo" HeaderText="#" SortExpression="ttNo" ReadOnly="True" />
<asp:TemplateField HeaderText="Course Date" SortExpression="startDate">
<EditItemTemplate>
<asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("startdate", "{0:M/d/yyyy}") %>'></asp:TextBox>
<asp:CalendarExtender ID="TextBox3_CalendarExtender" runat="server" Enabled="True"
TargetControlID="TextBox3" Format="M/d/yyyy">
</asp:CalendarExtender>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("startdate", "{0:M/d/yyyy}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Expiry Date" SortExpression="endDate">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("enddate", "{0:M/d/yyy}") %>'></asp:TextBox>
<asp:CalendarExtender ID="TextB开发者_开发知识库ox1_CalendarExtender" runat="server" Enabled="True"
TargetControlID="TextBox1" Format="M/d/yyyy">
</asp:CalendarExtender>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblEndDate" runat="server" Text='<%# Bind("enddate", "{0:M/d/yyyy}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>No valid courses found.</EmptyDataTemplate>
</asp:GridView>
UPDATE: I've been trying all your suggestions, but I get exceptions or nulls or empty strings. I've even re-created the problem in a simpler example and still can't figure it out! I'll keep trying though, and I appreciate any new suggestions.
Part 1 - Missing Text
You are probably getting blank values in the first part due to a need to access a child control:
String str = ((DataBoundLiteralControl)e.Row.Cells[6].Controls[0]).Text;
To see if your cells have any values in debug mode (check text in debug output window):
void grvValidCourses_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
System.Diagnostics.Trace.WriteLine(e.Row.Cells.Count);
foreach (TableCell c in e.Row.Cells)
{
System.Diagnostics.Trace.WriteLine(c.Text);
}
}
}
Part 2 - Missing Control
This is wrong:
Label lbl = (Label) grvValidCourses.FindControl("lblEndDate"); // null
You can't search the gridview for a row's control. You need to search the row.
Label lblProductOptionGrpName = (Label)e.Row.FindControl("lblProductOptionGrpName");
Part 3 - Accessing DataItem
DataBinder.Eval(e.Row.DataItem, "ColumnName")
Finally, I'm not sure what you're doing with your anonymous types, but you may need to check the contents before accessing properties:
if(MyControl.GetType() == typeof(HyperLink))
{
HyperLink TestLink = (HyperLink)MyControl;
TestLink .Visible = false;
}
Okay I finally figured out what is going on! I can only access the bound field through the row (e.g. e.Row.Cells[index].Text
). So I used the bound field to get the ID of my item, then found the item in the database, got the date, compared it, and highlighted the row's cells. Not the most efficient way, but it works.
Code from simple sample:
Grid View Front End
<asp:GridView ID="gdv" runat="server" AutoGenerateColumns="True" OnSelectedIndexChanged="gdv_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" SelectText="Select" />
<asp:BoundField DataField="id" HeaderText="#" ReadOnly="True" />
<asp:TemplateField HeaderText="CategoryName" >
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Description" >
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("desc") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Label ID="lblSelected" runat="server" Text="No row selected"></asp:Label>
Code Behind Page
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
var qry = ctx.Categories
.Select(c => new {
id = c.CategoryID,
name = c.CategoryName,
desc = c.Description,
});
gdv.DataSource = qry;
gdv.DataBind();
}
}
protected void gdv_SelectedIndexChanged(object sender, EventArgs e) {
selectRow();
}
private void selectRow() {
GridViewRow row = gdv.SelectedRow;
String strId = row.Cells[1].Text; // Bound Field column
lblSelected.Text = strId;
// use ID to get object from database...
}
If you can post markup, then it will be possible to figure out your issue.
You are doing this in wrong way,
this DataRowView rowView = (DataRowView)e.Row.DataItem;
should be DataRow rowView = ((DataRowView)e.Row.DataItem).Row;
protected void gridPanne_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType==DataControlRowType.DataRow)
{
Label label = (Label)e.Row.FindControl("Label4");
lbl.Text += " ** / ** "+label.Text;
}
}
精彩评论