Поиск элементов управления внутри вложенных главных страниц - PullRequest
8 голосов
/ 08 апреля 2009

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

Когда я вставляю элементы управления в ContentPlaceHolder с именем «bcr» - я должен найти элементы управления следующим образом:

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

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

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

Спасибо

Ответы [ 6 ]

23 голосов
/ 08 апреля 2009

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

/// <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");

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

4 голосов
/ 08 апреля 2009

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

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

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

4 голосов
/ 08 апреля 2009

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

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

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

Вы попадаете на объект главной страницы из любого элемента управления следующим образом:

C #:

this.Page;

VB.NET

Me.Page

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

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

Используя приведенный ниже код (VB.NET), скажем, вашу папку AppCode, все ваши элементы управления теперь будут выполнять рекурсивный поиск, вызывая 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
2 голосов
/ 11 октября 2012

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

Звоните:

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;
    }
}
1 голос
/ 08 апреля 2010

Я использовал <%@ MasterType VirtualPath="~/MyMaster.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;
        }

    }

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

0 голосов
/ 30 июля 2010

Я только что отлично заработал.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...