Проблема с asp:ContentPlaceHolder и блоками кода

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

Из того, что я испытал, симптомы этого состоят в том, что ваше приложение показывает длинный черный экран во время инициализации, но после отладки вы обнаружите, что ни один из ваших методов Application / Activity onCreate ] еще даже нельзя назвать , пока он виден.

7
задан Community 23 May 2017 в 11:58
поделиться

3 ответа

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

Итак, я проверял различия в коллекции ContentPlaceHolder.Controls между тем, как они заполняются. Я заметил, что при использовании блока кода он переворачивается только для чтения. В любой другой момент он будет просто пустым или заполненным.

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

ContentPlaceHolderExtensions.cs

public static class ContentPlaceHolderExtensions
{
    public static bool ContainsControlsOrCodeBlock(this ContentPlaceHolder placeHolder)
    {
        if (placeHolder.Controls.Count > 0)
             return true;

        return placeHolder.Controls.IsReadOnly;
    }
}

И затем проверьте это на главной странице:

Site.Master

<asp:ContentPlaceHolder ID="Content1" runat="server" />
<asp:ContentPlaceHolder ID="Content2" runat="server" />
<asp:ContentPlaceHolder ID="Content3" runat="server" />

<div>Content1: <%= Content1.Controls.Count %></div>
<div>Content2: <%= Content2.Controls.Count %></div>
<div>Content3: <%= Content3.Controls.Count %></div>

<div>Content1 (Ex. Meth.): <%= Content1.ContainsControlsOrCodeBlock() %></div>
<div>Content2 (Ex. Meth.): <%= Content2.ContainsControlsOrCodeBlock() %></div>
<div>Content3 (Ex. Meth.): <%= Content3.ContainsControlsOrCodeBlock() %></div>

В качестве доказательства концепции я добавил страницу с контентом:

Index.aspx

<asp:Content ContentPlaceHolderID="Content1" runat="server">
Plain Text Content
</asp:Content>

<asp:Content ContentPlaceHolderID="Content2" runat="server">
<%= "Code block content" %>
</asp:Content>

И все отрисовано, как ожидалось (я полагаю) ..

TBH, пока это не идеально .. Не думаю, что в этой ситуации мы сможем добиться большей элегантности. Я не уверен, как настраиваются другие коллекции элементов управления в этих различных сценариях, поэтому я подключился только к элементу управления ContentPlaceHolder .. Другие шаблонные элементы управления могут работать или не работать одинаково.

Мысли?

Вы можете загрузить проект из здесь :

http://code.google.com/p/robcthegeek/source/browse/#svn/trunk/stackoverflow/964724

8
ответ дан 6 December 2019 в 19:41
поделиться

Коллекция элементов управления пуста, потому что при наличии тегов сценария <% =%> буквальные элементы управления не добавляются в дерево элементов управления. Однако серверные элементы управления по-прежнему будут добавляться. Итак:

<asp:Content ID="Content2" ContentPlaceHolderID="Content2" Runat="Server">
     <%= "Code block content." %>
     <asp:GridView runat="server" ID="gvTest" />
</asp:Content>

<div>Content2: <%= Content2.Controls.Count %></div>

вернет

Контент 2: 1

У Рика Стрела есть отличная статья , в которой объясняется это поведение :

Чтобы заставить такой код работать, ASP.NET необходимо переопределить рендеринг конкретный контейнер, в котором любой код сценария размещен. Он делает это используя SetRenderMethodDelegate на контейнер и создание собственного метод рендеринга ...

Вместо создания элемента управления элементы управления литералом дерева, только ASP.NET добавляет серверные элементы управления к элементу управления дерево, когда теги <%%> присутствуют для контейнер. Чтобы справиться с буквальным содержимое и разметка скрипта, ASP.NET генерирует собственный метод рендеринга. Затем этот метод явно записывает любой статический HTML-контент и любой скрипт выражения с использованием HTML TextWriter. Любой код скрипта (<%%>) генерируется как исходный код самого метода.

К сожалению, я не могу придумать элегантного решения этой головоломки.

2
ответ дан 6 December 2019 в 19:41
поделиться

Слишком много для комментария, вот полный код, который у меня наконец-то заработал (адаптированный из ответа @Rob Cooper):

public static bool HasContent( this ContentPlaceHolder placeHolder )
{
    if ( placeHolder.Controls.Count > 0 )
    {
        LiteralControl textBlock;
        ContentPlaceHolder subContent;

        foreach ( var ctrl in placeHolder.Controls )
            if ( (textBlock = ctrl as LiteralControl) != null )
            {   //lit ctrls will hold any blocks of text
                if ( textBlock.Text != null && textBlock.Text.Trim() != "" )
                    return true;
            }
            else if ( (subContent = ctrl as ContentPlaceHolder) != null )
            {   //sub content controls should call this recursively
                if ( subContent.HasContent() )
                    return true;
            }
            else return true;   //any other control counts as content

        //controls found, but all are empty
        return false;
    }

    //if any code blocks are used the render mode will be different and no controls will
    //be in the collection, however it will be read only
    return placeHolder.Controls.IsReadOnly;
}

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

3
ответ дан 6 December 2019 в 19:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: