Получить текст гиперссылки, которая находится внутри поля шаблона в представлении сетки

Вроде бы легко, но мне с этим тяжело.

    <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>

В последнем столбце gridview есть кнопка. Нажмите эту кнопку, чтобы обновить базу данных и обновить gridview. Он также просматривает столбец идентификатора в представлении сетки и пытается выделить отредактированную строку.

Код работает без проблем, если поле ID является ограниченным полем и не является URL-адресом. Но когда это URL-адрес, я не могу прочитать текстовое значение URL-адреса. Я пробовал различные решения (помощь от SO и онлайн)

Ссылка HyperLink = (HyperLink) row.FindControl ("id"); // не работает

((HyperLink)GridView1.Rows[i].Cells[0].Controls[0]).Text // не работает

Это фрагмент кода, с которым мне нужна помощь

            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;
                     }
                }
            }

Я использую button.CommandName для хранения поля идентификатора, которое отлично работает. Я просто не могу найти элемент управления гиперссылкой в ​​​​сетке внутри поля шаблона.

Я получаю следующую ошибку, которая не имеет для меня смысла

Невозможно привести объект типа «System.Web.UI.DataBoundLiteralControl» к типу «System.Web.UI.WebControls.HyperLink».

Update1 Этот код работает без сбоев, если я не использую поле гиперссылки.

 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;
                        }
                    }

Если изменить столбец 0 на гиперссылку и изменить соответствующий код, то это не сработает. Очевидно, что чтение неправильной ячейки не является проблемой.

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;
 }
                }

person Hammad Khan    schedule 09.08.2013    source источник


Ответы (1)


Перво-наперво — вы пытаетесь FindControl("id"); где ваш элемент управления в представлении дизайна фактически находится ID — Регистр имеет значение.

Еще одна вещь - это также похоже на то, что <a> на самом деле не является элементом управления HyperLink, а на самом деле является элементом HtmlGenericControl, поэтому попытка разыграть свой элемент управления ни к чему не приводит.

Вы можете сделать одно из двух: изменить код программной части, чтобы получить HtmlGenericControl link = (HtmlGenericControl )row.FindControl("ID");.

Или измените представление дизайна и используйте элемент управления <asp:Hyperlink> вместо HTML <a>.

Ваша ошибка Unable to cast object of type 'System.Web.UI.DataBoundLiteralControl' (which is ain HTML terms) to type 'System.Web.UI.WebControls.HyperLink'.

Говорит ((HyperLink)GridView1.Rows[i].Cells[0].Controls[0], что элемент управления в позиции 0 в первой ячейке строки, которую вы обрабатываете, является литералом, а НЕ ссылкой. Вы можете попытаться обмануть его, взглянув вместо этого на Controls[1].

вы можете просмотреть визуализированный HTML-код вашей таблицы и убедиться в этом - ваша ссылка будет вложена в диапазон или рядом с диапазоном.

Изучите Controls в отладке и посмотрите, что на самом деле в нем содержится.

Обновить

Существует много путаницы в том, КАК вы называете свой код. У вас есть e.Row.RowType, что наводит меня на мысль, что вы делаете это в RowDataBound.

Если это так, то вам НЕ нужно перебирать все строки вашего gridview, поскольку этот метод вызывается для каждой строки, поэтому вы будете вызывать каждую строку, а затем каждую строку в сетке. ОГРОМНОЕ количество циклов, происходящих для большая сетка.

Так что попробуйте это вместо этого - он заинтересован только в этой одной строке.

также - не знаю, откуда вы получаете свой button.CommandName

Для этого вам нужно будет проверить свой метод FindControl, чтобы убедиться, что он действительно является элементом управления гиперссылкой.

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;
    }
}

последнее обновление...

Хорошо - после дополнительных комментариев я считаю, что вам нужно рекурсивно искать элемент управления. это потому, что FindControl будет смотреть только на прямые элементы управления внутри элемента управления. он не найдет элементы управления в элементах управления внутри вашего элемента управления - IE FindControl просматривает только первые дочерние элементы, а не внуки.

Поэтому создайте этот метод где угодно:

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;
}

Затем передайте свою строку и идентификатор элемента управления, который вы ищете.

Вот так - меняй:

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

к этому - обратите внимание, я сохранил ваш нижний регистр id - не уверен, используете ли вы строчные или прописные буквы - этот метод выследит для вас маленького жука :)

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

Когда у вас есть контроль, вы можете применить его к тому, что вам нужно/или должно быть

person Darren Wainwright    schedule 09.08.2013
comment
Хорошо, ID на самом деле что-то другое, так что это не проблема. Я пробовал HTMLGenericControl, все та же проблема. Я обновил сообщение об ошибке в своем POST. Хотя у тебя была хорошая догадка. - person Hammad Khan; 09.08.2013
comment
еще одно обновление для вас - и, кстати, ID БУДЕТ проблемой, если вы реализуете первое обновление. вам не нужно будет иметь все эти ячейки [0]... тогда вы обнаружите, что ID на самом деле ваша проблема :) - person Darren Wainwright; 09.08.2013
comment
ок такая же проблема. Вот ошибка с вашим последним кодом Object reference not set to an instance of an object. Я возился с ним в режиме отладки и смотрел на ячейку [1] и так далее. Как я уже упоминал, код отлично работает, если это просто текст внутри ячейки. Но это не работает для ‹a href= id=myid value=›value‹/› внутри ячейки. - person Hammad Khan; 09.08.2013
comment
хорошо, так что link, скорее всего, ничего, что означает, что он его не нашел. попробуйте изменить HtmlGenericControl на Control, а затем проверьте его - IE поставьте точку останова в этой строке и посмотрите, что (если есть) link IS. - person Darren Wainwright; 09.08.2013
comment
Это может помочь, если вы также опубликуете полный метод и убедитесь, что идентификаторы совпадают СОВЕРШЕННО - person Darren Wainwright; 09.08.2013
comment
см. обновление 1 в сообщении. На самом деле проблема заключается именно в этом блоке кода, как получить доступ к гиперссылке внутри gridview. Остальной код работает отлично. - person Hammad Khan; 09.08.2013
comment
Хорошо, вы говорите мне, что это всего лишь этот блок кода... и я говорю вам, что нам нужно увидеть весь метод - вы вызываете его нажатием кнопки внутри строки в вашей сетке? вызывая таким образом RowCommand? Или вы используете RowDataBound? Если это так, нам нужно знать, так как весь ваш код не подходит для этого... - person Darren Wainwright; 09.08.2013
comment
Этот код находится внутри события нажатия кнопки, которое находится внутри gridView [последний столбец]. Я не использую какие-либо события gridview. Я попытался заменить ‹a href= на ‹asp:hyerlink… все та же ошибка. В основном весь код, найденный в ячейке [0], является System.Web.UI.LiteralControl. - person Hammad Khan; 09.08.2013
comment
Хорошо, я изменил свое обновление, потому что вижу row.rowtype в вашем коде, который является частью rowdatabound. В противном случае - я понятия не имею, не видя всего этого. слишком много битов не хватает, чтобы помочь - извините - person Darren Wainwright; 09.08.2013
comment
@darrent, это одна из вещей, которые скопированы из другого вопроса SO для решения проблемы, но не сработали. Первоначально мой код работал нормально без этого. - person Hammad Khan; 09.08.2013
comment
В качестве примечания: если вы хотите прокручивать сетку, как вы, вам нужно выполнить рекурсивный поиск идентификатора элемента управления, поскольку FindControl ТОЛЬКО просматривает прямые дочерние элементы, а не дочерние элементы управления дочерними элементами. - person Darren Wainwright; 09.08.2013
comment
Я пробовал row.Cell[0].FindControl, но это не возвращает правильный элемент управления. - person Hammad Khan; 09.08.2013
comment
вот почему я говорю, что вам нужно выполнить ресурсивный поиск, чтобы вы могли развернуть, чтобы найти правильный элемент управления во всех элементах управления дочерними и внуками - добавление обновления с помощью рекурсивного метода - это наверняка найдет ваш элемент управления - person Darren Wainwright; 09.08.2013
comment
хорошо, позвольте мне сделать это правильно, хотя я точно знаю, что я смотрю в ячейку [0], которая является первой ячейкой. - person Hammad Khan; 09.08.2013
comment
да, но ваша ссылка находится внутри литерала, и findcontrol ее не получит - используйте рекурсивный метод, который я только что добавил в обновление. - person Darren Wainwright; 09.08.2013
comment
Ошибка исчезла, но код работает неправильно. Я не могу отлаживать, так как значения отладки недоступны из-за оптимизированного кода... копаться... - person Hammad Khan; 09.08.2013