2009-04-08 2 views
8

У меня есть главная страница, вложенная в 2 уровня. У этого есть главная страница, и у главной страницы есть главная страница.Поиск элементов управления внутри вложенных основных страниц

Когда я придерживаюсь управления в ContentPlaceHolder с именем «BCR» - Я должен найти элементы управления, как так:

Label lblName =(Label)Master.Master.FindControl("bcr").FindControl("bcr").FindControl("Conditional1").FindControl("ctl03").FindControl("lblName"); 

ли я полностью потерял? Или это как это нужно сделать?

Я собираюсь работать с MultiView, который находится внутри условного контроля содержимого. Итак, если я хочу изменить представление, мне нужно получить ссылку на этот элемент управления правильно? Получение этой ссылки будет еще более неприятно! Есть ли способ лучше?

Благодаря

ответ

4

Во-первых, вы должны знать, что на самом деле MasterPages сидеть внутри страницы. Настолько, что событие Load MasterPage фактически вызывается после события загрузки ASPX.

Это означает, что объект страницы фактически является самым высоким элементом управления в иерархии управления.

Итак, зная это, лучший способ найти какой-либо элемент управления в такой вложенной среде - это написать рекурсивную функцию, которая проходит через каждый элемент управления и дочерний элемент управления, пока не найдет тот, который вы ищете. в этом случае ваши MasterPages на самом деле являются дочерними элементами управления главной страницы.

Вы к основному объекту страницы внутри какого-либо контроля, как это:

C#:

this.Page;

VB.NET

Me.Page

Я считаю, что, как правило, метод контрольного класса FindControl() довольно бесполезно, так как окружающая среда всегда вложенный.

Потому что, если это, я решил использовать возможности .NET 3.5 Extension для расширения класса Control.

Используя приведенный ниже код (VB.NET), скажем, в вашей папке AppCode, все ваши средства управления теперь peform рекурсивный находку по телефону FindByControlID()

Public Module ControlExtensions 
    <System.Runtime.CompilerServices.Extension()> _ 
    Public Function FindControlByID(ByRef SourceControl As Control, ByRef ControlID As String) As Control 
     If Not String.IsNullOrEmpty(ControlID) Then 
      Return FindControlHelper(Of Control)(SourceControl.Controls, ControlID) 
     Else 
      Return Nothing 
     End If 
    End Function 

    Private Function FindControlHelper(Of GenericControlType)(ByVal ConCol As ControlCollection, ByRef ControlID As String) As Control 
     Dim RetControl As Control 

     For Each Con As Control In ConCol 
      If ControlID IsNot Nothing Then 
       If Con.ID = ControlID Then 
        Return Con 
       End If 
      Else 
       If TypeOf Con Is GenericControlType Then 
        Return Con 
       End If 
      End If 

      If Con.HasControls Then 
       If ControlID IsNot Nothing Then 
        RetControl = FindControlByID(Con, ControlID) 
       Else 
        RetControl = FindControlByType(Of GenericControlType)(Con) 
       End If 

       If RetControl IsNot Nothing Then 
        Return RetControl 
       End If 
      End If 
     Next 

     Return Nothing 
    End Function 

End Module 
22

Нахождение управления является боль, и Я использую этот метод, который я получил от CodingHorror blog довольно давно, с одной модификацией, которая возвращает нулевое значение, если пустой идентификатор передается в.

/// <summary> 
/// Recursive FindControl method, to search a control and all child 
/// controls for a control with the specified ID. 
/// </summary> 
/// <returns>Control if found or null</returns> 
public static Control FindControlRecursive(Control root, string id) 
{ 
    if (id == string.Empty) 
     return null; 

    if (root.ID == id) 
     return root; 

    foreach (Control c in root.Controls) 
    { 
     Control t = FindControlRecursive(c, id); 
     if (t != null) 
     { 
      return t; 
     } 
    } 
    return null; 
} 

в вашем случае, я думаю, что вам нужно следующие:

Label lblName = (Label) FindControlRecursive(Page, "lblName"); 

Использование этого метода, как правило, гораздо удобнее, так как вам не нужно точно знать, где находится элемент управления (при условии, что вы знаете идентификатор, конечно), хотя, если у вас есть вложенные элементы управления с одно и то же имя, вы, вероятно, столкнетесь с каким-то странным поведением, так что это может быть чем-то, на что можно обратить внимание.

+0

Это работает отлично. Благодарю. –

+0

+1 спасибо, это тоже помогло мне – leen3o

+0

+1 Я знаю, что это похоже на 5 лет, но этот метод спас мне некоторую головную боль, спасибо! – psoshmo

4

Хотя я люблю рекурсию и согласен с Анди и Мун, еще один подход, который вы можете рассмотреть, это иметь strongly typed Master page. Все, что вам нужно сделать, это добавить одну директиву на страницу aspx.

Вместо того, чтобы обращаться к странице с главной страницы, рассмотрите возможность доступа к элементу управления на главной странице с самой страницы. Этот подход имеет большой смысл, если на главной странице есть метка заголовка, и вы хотите установить ее значение с каждой страницы, использующей мастер.

Я не уверен на 100%, но я думаю, что это будет более простая техника с вложенными главными страницами, поскольку вы просто укажете VirtualPath на мастер, содержащий элемент управления, к которому вы хотите получить доступ. Это может показаться сложным, если вы хотите получить доступ к двум элементам управления, по одному на каждой соответствующей главной странице.

+0

Да, хороший момент. Иногда это полезно только для того, чтобы поместить эту функциональность в какой-то метод или свойство в вашу пользовательскую страницу. Хотя, конечно, не вредно иметь встроенные рекурсивные средства управления – andy

1

Я использовал метод <%@ MasterType VirtualPath="~/MyMaster.master" %>. У меня есть свойство на главной главной странице, а затем на главной странице главной страницы другое свойство с тем же именем, вызывающим основное свойство master, и оно отлично работает.

У меня есть это в основном главная страница

public string MensajeErrorString 
    { 
     set 
     { 
      if (value != string.Empty) 
      { 
       MensajeError.Visible = true; 
       MensajeError.InnerHtml = value; 
      } 
      else 
       MensajeError.Visible = false; 
     } 


    } 

это просто элемент DIV, который должен показать сообщение об ошибке. Я хотел бы использовать это же свойство на страницах с главной страницей-страницей (это вложен в основной мастер).

Затем в мастер подробно я это

public string MensajeErrorString 
    { 
     set 
     { 
       Master.MensajeErrorString = value; 
     } 

    } 

Im вызова основного главного свойства от мастера подробно, чтобы создать такое же поведение.

0

Я просто отлично его работаю.

В contentpage.aspx, я написал следующее:

If Master.Master.connectsession.IsConnected Then my coded comes in here End If

2

Вот код, который является более универсальным и работает с пользовательским условием (что может быть лямбда-выражение!)

Звоните:

Control founded = parent.FindControl(c => c.ID == "youdId", true); 

расширение управления

public static class ControlExtensions 
{ 
    public static Control FindControl(this Control parent, Func<Control, bool> condition, bool recurse) 
    { 
     Control founded = null; 
     Func<Control, bool> search = null; 
     search = c => c != parent && condition(c) ? (founded = c) != null : 
                recurse ? c.Controls.FirstOrDefault(search) != null : 
                (founded = c.Controls.FirstOrDefault(condition)) != null; 
     search(parent); 
     return founded; 
    } 
} 
Смежные вопросы