Добавление в коллекцию элементов управления страницы из пользовательского элемента управления - PullRequest
5 голосов
/ 12 февраля 2011

У меня есть пользовательский контроль asp.net, который представляет всплывающее диалоговое окно. По сути, это оболочка для диалогового окна пользовательского интерфейса jQuery, которая может быть разделена на подклассы для простого создания диалогов.

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

Проблема в том, что я не могу найти безопасный способ вставить этот div на страницу. У usercontrol нет события preinit, поэтому я не могу сделать это там, и вызов Page.Form.Controls.Add (...) в Init, Load или PreRender вызывает стандартное исключение «Коллекция элементов управления не может быть изменена во время фаз DataBind, Init, Load, PreRender или Unload. "

Я думал, что нашел решение, используя ...

ScriptManager.RegisterClientScriptBlock(Page, Me.GetType, UniqueID + "_Dialog_Div", containerDiv, False)

... которая, казалось, работала нормально, но недавно коллега попыталась поместить UpdatePanel в диалог, и теперь она получает ошибку "Тег сценария зарегистрирован для типа 'ASP.controls_order_viewzips_ascx' и ключа 'ctl00 $ ContentBody $ OViewZips_Dialog_Div 'содержит недопустимые символы вне тегов сценария:. Только правильно отформатированные теги сценария могут быть зарегистрированы. "

Как вы должны добавить элементы управления в коллекцию элементов управления страницы из пользовательского элемента управления?

Ответы [ 2 ]

7 голосов
/ 15 февраля 2011

Я не уверен, почему вам действительно нужно добавить этот div в форму страницы, но это должно работать:

  Public Class WebUserControl1
    Inherits System.Web.UI.UserControl

        Private Sub UC_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
            AddHandler Me.Page.Init, AddressOf Me.Page_Init
        End Sub

        Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
            Dim dialogDiv As New Panel
            dialogDiv.ID = "DialogDiv"
            If Not Page.Form.Controls.Contains(dialogDiv) Then
                Page.Form.Controls.AddAt(0, dialogDiv)
            End If
        End Sub

    End Class

Как реализовать это в C #.Я всегда получаю сообщение об ошибке Невозможно изменить коллекцию элементов управления при загрузке, PreRender. Мне нужен литеральный элемент управления, добавляемый в заголовок моей главной страницы из пользовательского элемента управления.Элемент управления Literal будет содержать ссылку CSS.

Хотите добавить литерал к элементу управления HeadContent -ContentPlaceHolder в мастере или в заголовок страницы (элемент заголовка html)?Однако, здесь я показываю оба.

Вот код вашего UserControl:

public partial class UC_AddToMaster : System.Web.UI.UserControl
{
    private void Page_Init(object sender, System.EventArgs e)
    {
        this.Page.Init += UC_AddToMaster_Init;
    }

    private void UC_AddToMaster_Init(object sender, EventArgs e)
    {
        Literal literal = new Literal{ Text = "Hi World!" };
        // if you want to add it to the header of the page:
        if (!Page.Header.Controls.Contains(literal))
        {
            Page.Header.Controls.AddAt(0, literal);
        }

        // if you want to add it to the master's HeadContent ContentPlaceHolder control:
        var siteMaster = Page.Master as SiteMaster;
        if (siteMaster != null)
        {
            if (!siteMaster.Head.Controls.Contains(literal))
            {
                siteMaster.Head.Controls.AddAt(0, literal);
            }
        }
    }
}

Для упомянутого выше подхода HeadContent я предоставил следующее свойство в мастере:

// in the master
public ContentPlaceHolder Head { get { return this.HeadContent; } }

Поэтому мне нужно было привести мастера страницы к его фактическому типу (SiteMaster здесь) в UserControl.В противном случае я не смог бы получить доступ к этому свойству.

4 голосов
/ 14 февраля 2011

Usercontrol не имеет события PreInit, но ничто не мешает вам добавить обработчик к событию PreInit страницы в вашем UserControl:

Page.PreInit += new EventHandler(Page_PreInit);

edit - вы правы - вы не можете захватитьPreInit из usercontrol, хотя я удивлен, что вы не можете - но вы все равно можете изменить коллекцию элементов управления страницы, добавив код в конструктор UserControl.Я попробовал это, и это работает.

public MyUsercontrol()
{
    Page page = (Page)HttpContext.Current.Handler;
    Literal lit = new Literal();
    lit.Text="text";
    page.Controls.Add(lit);
}

Добавление обработчика событий к Page.PreInit в конструкторе компилируется, но он никогда не запускается.

(конец редактирования)

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

...