Использование FindControl() для поиска элемента управления
У меня есть Literal
контролировать, что я пытаюсь найти, чтобы я мог вставить текст в него. У меня есть главная страница, которая содержит несколько заполнителей контента.
<asp:Content ID="Content7" ContentPlaceHolderID="MainLinks" runat="server">
<h3>Project Navigation</h3>
<ul class="rightColBoxNav">
<asp:Literal ID="litNavLinks" runat="server" />
</ul>
</asp:Content>
Я продолжаю получать "Ссылка на объект не установлена на экземпляр объекта". Как мне найти этот объект, чтобы я мог найти и обновить его?
Я пытался:
((Literal)Page.FindControl("litNavLinks")).Text = sb.ToString();
((Literal)Page.Page.FindControl("litNavLinks")).Text = sb.ToString();
((Literal)Page.FindControl("Content7").FindControl("litNavLinks")).Text = sb.ToString();
но безрезультатно. Как определить местоположение?
5 ответов
Из мастер-страницы:
var literal = (Literal)FindControl("MainLinks").FindControl("litNavLinks");
literal.Text = sb.ToString();
Изнутри зрения:
litNavLinks.Text = sb.ToString();
Я бы попробовал другой подход.
Как насчет использования пользовательского элемента управления и предоставления соответствующих свойств для получения или установки текстового значения.
Свойство будет доступ к буквальному управлению. Однако страница, вызывающая свойство, не будет мудрее.
Помните, что мы живем в мире ОО.
Элемент управления ASP ContentPlaceHolder является "контейнером именования" (он реализует интерфейс INamingContainer). Метод Control.FindControls ищет только в текущем контейнере именования элемент управления с указанным идентификатором.
Иногда я включал служебную функцию, которая принимает строку с разделителями "/" для произвольной навигации по контейнерам имен на странице. Что-то вроде следующей реализации. (Примечание: я не пытался скомпилировать или протестировать этот код)
public static Control FindControlByPath(this Control start, string controlPath)
{
if(controlPath == null)
throw new ArgumentNullException("controlPath");
string[] controlIds = controlPath.split('/');
Control current = start;
if(controlIds[0] == "") // in case the control path starts with "/"
current = start.Page; // in that case, start at the top
for(int i=0; i<controlIds.Length; i++)
{
switch(controlIds[i])
{
case "":
// TODO: handle syntax such as "<controlId>//<controlId>", if desired
break;
case ".":
// do nothing, stay on the current control
break;
case "..":
// navigate up to the next naming container
current = current.Parent;
if(current == null)
throw new ArgumentOutOfRangeException("No parent naming container exists.", "controlPath");
while(!(current is INamingContainer))
{
current = current.Parent;
if(current == null)
throw new ArgumentOutOfRangeException("No parent naming container exists.", "controlPath");
}
break;
default:
current = current.FindControl(controlIds[i]);
break;
}
}
return current;
}
Итак, в вашем случае вы сможете сделать следующее:
<some control>.FindControlByPath("/MainLinks/litNavLinks").Text = sb.ToString();
или же
Page.FindControlByPath("MainLinks/litNavLinks").Text = sb.ToString();
Я думаю, что вы должны сделать это, но у меня нет моего кода, чтобы перепроверить прямо сейчас:
Page.Master.FindControl("MainLinks").FindControl("litNavLinks");
Literal tbx = this.Controls.Find("Literal1", true).FirstOrDefault() as Literal;