Question

string percentage = e.Row.Cells[7].Text;

I am trying to do some dynamic stuff with my GridView, so I have wired up some code to the RowDataBound event. I am trying to get the value from a particular cell, which is a TemplateField. But the code above always seems to be returning an empty string.

Any ideas?

To clarify, here is a bit the offending cell:

<asp:TemplateField HeaderText="# Percentage click throughs">
<ItemTemplate>
    <%# AddPercentClickThroughs((int)Eval("EmailSummary.pLinksClicked"), (int)Eval("NumberOfSends")) %>
</ItemTemplate>
</asp:TemplateField>

On a related note, does anyone know if there is a better way of selecting the cell in the row. It sucks putting in cell[1]. Couldn't I do cell["mycellname"], so if I decide to change the order of my cells, bugs wont appear?

Was it helpful?

Solution

First you need to wrap your code in a Label or Literal control so that you can reference it properly. What's happening is that there's no way for the system to keep track of it, because there's no control associated with the text. It's the control's responsibility to add its contents to viewstate.

You need to use gridView.FindControl("controlName"); to get the control in the row. From there you can get at its properties including Text.

You can also get at the DataItem property of the Row in question and cast it to the appropriate type and extract the information directly.

OTHER TIPS

why not pull the data directly out of the data source.

DataBinder.Eval(e.Row.DataItem, "ColumnName")

When you use a TemplateField and bind literal text to it like you are doing, asp.net will actually insert a control FOR YOU! It gets put into a DataBoundLiteralControl. You can see this if you look in the debugger near your line of code that is getting the empty text.

So, to access the information without changing your template to use a control, you would cast like this:

string percentage = ((DataBoundLiteralControl)e.Row.Cells[7].Controls[0]).Text;

That will get you your text!

The above are good suggestions, but you can get at the text value of a cell in a grid view without wrapping it in a literal or label control. You just have to know what event to wire up. In this case, use the DataBound event instead, like so:

protected void GridView1_DataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        if (e.Row.Cells[0].Text.Contains("sometext"))
        {
            e.Row.Cells[0].Font.Bold = true;
        }
    }
}

When running a debugger, you will see the text appear in this method.

Just use a loop to check your cell in a gridview for example:

for (int i = 0; i < GridView2.Rows.Count; i++)
{
    string vr;
    vr = GridView2.Rows[i].Cells[4].Text; // here you go vr = the value of the cel
    if (vr  == "0") // you can check for anything
    {
        GridView2.Rows[i].Cells[4].Text = "Done";
        // you can format this cell 
    }
}

use RowDataBound function to bind data with a perticular cell, and to get control use (ASP Control Name like DropDownList) GridView.FindControl("Name of Control")

I had a similar question, but found the solution through a slightly different approach. Instead of looking up the control as Chris suggested, I first changed the way the field was specified in the .aspx page. Instead of using a <asp:TemplateField ...> tag, I changed the field in question to use <asp:BoundField ...>. Then, when I got to the RowDataBound event, the data could be accessed in the cell directly.

The relevant fragments: First, the aspx page:

<asp:GridView ID="gvVarianceReport" runat="server" ... >
...Other fields...
    <asp:BoundField DataField="TotalExpected" 
     HeaderText="Total Expected <br />Filtration Events" 
     HtmlEncode="False" ItemStyle-HorizontalAlign="Left" 
     SortExpression="TotalExpected" />
...
</asp:Gridview>

Then in the RowDataBound event I can access the values directly:

protected void gvVarianceReport_Sorting(object sender, GridViewSortEventArgs e)
{
    if (e.Row.Cells[2].Text == "0")
    {
        e.Row.Cells[2].Text = "N/A";
        e.Row.Cells[3].Text = "N/A";
        e.Row.Cells[4].Text = "N/A";
    }
}

If someone could comment on why this works, I'd appreciate it. I don't fully understand why without the BoundField the value is not in the cell after the bind, but you have to look it up via the control.

Label lblSecret = ((Label)e.Row.FindControl("lblSecret"));
<asp:TemplateField HeaderText="# Percentage click throughs">
  <ItemTemplate>
    <%# AddPercentClickThroughs(Convert.ToDecimal(DataBinder.Eval(Container.DataItem, "EmailSummary.pLinksClicked")), Convert.ToDecimal(DataBinder.Eval(Container.DataItem, "NumberOfSends")))%>
  </ItemTemplate>
</asp:TemplateField>


public string AddPercentClickThroughs(decimal NumberOfSends, decimal EmailSummary.pLinksClicked)
{
    decimal OccupancyPercentage = 0;
    if (TotalNoOfRooms != 0 && RoomsOccupied != 0)
    {
        OccupancyPercentage = (Convert.ToDecimal(NumberOfSends) / Convert.ToDecimal(EmailSummary.pLinksClicked) * 100);
    }
    return OccupancyPercentage.ToString("F");
}

If you set the attribute Visible on the asp:BoundField to False. Like this

<asp:BoundField DataField="F1" HeaderText="F1" Visible="False"/>

You will not get any Text in the Cells[i].Text property when you loop the rows. So

foreach (GridViewRow row in myGrid.Rows)
{
  userList.Add(row.Cells[0].Text); //this will be empty ""
}

But you can set a column not visible by connecting the grid to the event OnRowDataBound then from here do this

e.Row.Cells[0].Visible = false //now the cell has Text but it's hidden
protected void gvbind_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';";
        e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';";
        e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.gvbind, "Select$" + e.Row.RowIndex);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top