2

Seems to be easy but I am having a hard time with this.

    <asp:TemplateField HeaderText="ID" InsertVisible="False" SortExpression="id">
        <ItemTemplate>
            <a href="/visit.aspx?Id=<%#Eval("Id")%>" id="ID" name="ID">  <%#Eval("Id")%> </a>
        </ItemTemplate>
    </asp:TemplateField>

There is a button in the last column of gridview. Click this button updated the database and refreshed gridview. It also look at the id column in gridview and tries to highlight the row that was edited.

The code works without any problem if ID field is bounded field and is not a URL. But when it is a URL, I cannot seem to read the text value of the URL. I have tried various solution (help from SO and online)

HyperLink link = (HyperLink)row.FindControl("id"); // did not work

((HyperLink)GridView1.Rows[i].Cells[0].Controls[0]).Text // did not work

This is the code snippet that I need help with

            for (int i = 0; i < GridView1.Rows.Count; i++)
            {
                GridViewRow row;
                row = GridView1.Rows[i];
                if (row.RowType == DataControlRowType.DataRow)
                {

                    HyperLink link = (HyperLink)row.FindControl("id");
                    if (((HyperLink)GridView1.Rows[i].Cells[0].Controls[0]).Text == button.CommandName)
                    {
                        row.BackColor = System.Drawing.Color.IndianRed;
                     }
                }
            }

I am using button.CommandName to store the ID field which works fine. I just can't seem to find the hyperlink control in the gridview inside a template field.

I am getting the following error which does not make sense to me

Unable to cast object of type 'System.Web.UI.DataBoundLiteralControl' to type 'System.Web.UI.WebControls.HyperLink'.

Update1 This code works without hitch, if I do not use hyperlink field.

 for (int i = 0; i < GridView1.Rows.Count; i++)
                    {
                        GridViewRow row;
                        row = GridView1.Rows[i];
                        if (row.Cells[0].Text.Equals(button.CommandName))
                        {
                            row.BackColor = System.Drawing.Color.IndianRed;
                        }
                    }

If change the column 0 to hyperlink and change the code corresponding, then it does not work. Clearly reading the wrong cell is not the problem.

for (int i = 0; i < GridView1.Rows.Count; i++)
{
    GridViewRow row;
    row = GridView1.Rows[i];
    HtmlAnchor anchor = (HtmlAnchor) row.Cells[0].Controls[0];
    if ( anchor.InnerText.Equals(button.CommandName))
    {
        row.BackColor = System.Drawing.Color.IndianRed;
 }
                }
TheTechGuy
  • 16,560
  • 16
  • 115
  • 136

1 Answers1

2

First things first - you are trying to FindControl("id"); where your control in the design view is actually ID - Case matters.

Another thing - this also appears to be because <a> isn't actually a HyperLink control, but actually a HtmlGenericControl - thus trying to cast your control is resulting in nothing.

You could do one of two things - change your code-behind to get HtmlGenericControl link = (HtmlGenericControl )row.FindControl("ID");

Or change your design view and use an <asp:Hyperlink> control instead of the HTML <a>

Your error Unable to cast object of type 'System.Web.UI.DataBoundLiteralControl' (which is ain HTML terms) to type 'System.Web.UI.WebControls.HyperLink'.

Is saying ((HyperLink)GridView1.Rows[i].Cells[0].Controls[0] that the control at position 0 in the first cell on the row your processing is a literal and NOT a link. You can try to fudge it by looking at Controls[1] instead.

you can view the rendered HTML of your table and verify this - your link will be nested in a span, or next to a span..

Examine the Controls in debug and see what is actually contained in it.

Update

There is a lot of confusion over HOW your calling your code. You have e.Row.RowType which leads me to believe you're doing this in RowDataBound.

If this is the case then you do NOT need to loop through all of your gridview rows as this method gets called on every row - so you would be calling each row, then each row in the grid.. MASSIVE amount of looping going on for a big grid.

So try this instead - it is only interested on that one row.

also - not sure where you;re getting your button.CommandName from

For this you will need to examine your FindControl method to make sure it actually IS a hyperlink control

if ((e.Row.RowType == DataControlRowType.DataRow)) {
    GridViewRow row = e.Row;
    // get your link - if indeed the control IS a hyperlink
        // this will be null if the control "id" is NOT a hyperlink control
    HyperLink link = (HyperLink)row.FindControl("id");
    if ((link.Text == Button.CommandName)) {
        row.BackColor = Drawing.Color.IndianRed;
    }
}

last update...

Ok - after more comments I reckon you need to recursively search for the control. this is because FindControl will only look at the direct controls within a control. it will not find controls within controls within your control - I.E FindControl looks at the first children only and not grandchildren.

So create this method where ever you like:

public static Control FindControlRecursive(Control Root, string Id)
{
    if (Root.ID == Id) { return Root; }

    foreach (Control Ctl in Root.Controls)
    {
        Control FoundCtl = FindControlRecursive(Ctl, Id);
        if (FoundCtl != null) { return FoundCtl; }
    }
    return null;
}

Then pass in your row and the ID of the control you're looking for.

So like this - change:

 HyperLink link = (HyperLink)row.FindControl("id");

to this - notice i kept your lowercase id - not sure if you are using lowercase or uppercase - this method will hunt out the little bugger for you :)

Control link = FindControlRecursive(row, "id");

Once you have your control you can cast it to what you need/or it should be

Darren Wainwright
  • 30,247
  • 21
  • 76
  • 127
  • OK, ID is actually something else so that is not a problem. I tried HTMLGenericControl, still the same issue. I updated the error message in my POST. You had a good guess though. – TheTechGuy Aug 09 '13 at 17:42
  • another update for you - and BTW - ID WILL be the problem if you implement by first update. you won't need to have all that cells[0] stuff...you will then find that `ID` is in fact your problem :) – Darren Wainwright Aug 09 '13 at 17:47
  • ok same problem. Here is the error with your latest code `Object reference not set to an instance of an object`. I have fiddled with it in debug mode and looked at cell[1] and so on. As I mentioned the code works perfect if it is just text inside the cell. But it does not work for value> inside cell. – TheTechGuy Aug 09 '13 at 18:02
  • ok - so `link` is likely nothing - meaning it didn't find one. try changing `HtmlGenericControl` to `Control` and then examine it - I.E put a breakpoint at that line and see what (if anything) `link` IS. – Darren Wainwright Aug 09 '13 at 18:07
  • It migth help if you posted the complete method too and make sure ID's match PERFECTLY – Darren Wainwright Aug 09 '13 at 18:10
  • please see update 1 in the POST. Really the problem is just this block of code, how to access hyperlink inside gridview. The rest of the code works great. – TheTechGuy Aug 09 '13 at 18:12
  • Ok, you're telling me that it's just that block of code... and i am telling you we need to see the entire method - are you calling that from a button click inside a row on your grid? thus calling RowCommand? Or are you using RowDataBound? If so, we need to know - as all your code is wrong for this... – Darren Wainwright Aug 09 '13 at 18:57
  • This code is inside a button click event which is inside gridView [last column]. I am not using any of gridview events. I tried replacing – TheTechGuy Aug 09 '13 at 19:04
  • Ok - i have changed my update because i see row.rowtype in your code - which is part of rowdatabound. Failing that - I have no idea without seeing it all. there are too many bits missing to help anymore - sorry – Darren Wainwright Aug 09 '13 at 19:06
  • @darrent that is one of the things that copied from other SO question to solve the problem but did not work. Originally my code worked fine without this. – TheTechGuy Aug 09 '13 at 19:07
  • As a side note - if you want to loop through the grid like you are then you have to perform a recursive search for the control ID as FindControl ONLY looks at the direct children and not child controls of children – Darren Wainwright Aug 09 '13 at 19:08
  • I tried row.Cell[0].FindControl but this does not return the correct control – TheTechGuy Aug 09 '13 at 19:09
  • which is why i say you need to perform a resursive search so you can drill down to find the correct control within all the controls children and grandchildren - adding an update with a recursive method - this will for sure find your control – Darren Wainwright Aug 09 '13 at 19:14
  • ok let me do that right although I know for sure, I am looking into cell[0] that is first cell. – TheTechGuy Aug 09 '13 at 19:16
  • 1
    yah - but your link is inside the literal and findcontrol won't get it - use the recursive method i have just put in the update. – Darren Wainwright Aug 09 '13 at 19:19
  • The error has disappear but the code is not functioning correctly. I am not able to debug as it debug values are not available because of optimized code... digging in ... – TheTechGuy Aug 09 '13 at 19:37