Вопрос

У меня возникла проблема при использовании LoadControl( type, Params ).Позвольте мне объяснить...

У меня есть супер простое пользовательское управление (ascx)

<%@ Control Language="C#" AutoEventWireup="True" Inherits="ErrorDisplay" Codebehind="ErrorDisplay.ascx.cs" EnableViewState="false" %>

<asp:Label runat="server" ID="lblTitle" />
<asp:Label runat="server" ID="lblDescription" />

с кодом ( c # ) , стоящим за:

public partial class ErrorDisplay : System.Web.UI.UserControl
{

    private Message _ErrorMessage;    

    public ErrorDisplay()
    {
    }

    public ErrorDisplay(Message ErrorMessage)
    {
        _ErrorMessage = ErrorMessage;
    }    

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (_ErrorMessage != null)
        {
            lblTitle.Text = _ErrorMessage.Message;
            lblDescription.Text = _ErrorMessage.Description;
        }
    }
}

В другом месте моего веб-приложения я добавляю экземпляр usercontrol на страницу, используя следующий код:

divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails }));   

Я использую перегруженную версию LoadControl, потому что я хочу передать параметр Message конструктору.Все это появляется работать нормально.

Однако, когда OnPreRender() запускается в ErrorDisplay usercontrol переменные lblTitle и lblDescription являются обеими null, несмотря на то, что они имеют эквивалент разметки.Переменная message была заполнена правильно.

Кто-нибудь может пролить какой-либо свет на то, почему это может происходить?

Спасибо

Редактировать:

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

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

Это было полезно?

Решение

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

protected void Page_Load(object sender, EventArgs e)
{
    if (_ErrorMessage != null)
    {
        lblTitle.Text = _ErrorMessage.Message;
        lblDescription.Text = _ErrorMessage.Description;
    }
}

У меня было понимание, что функция LoadControl привела загружаемый элемент управления к текущему "состоянию" страницы, на которую он включается.следовательно, Init, Page_Load и т.д. Выполняются как часть вызова LoadControl.

Интересно, что это (без ответа) asp.net сообщение на форумах демонстрирует ту же проблему, что и у меня.

Сообщение на форумах MSDN

Дополнительно - Из MSDN:

Когда вы загружаете элемент управления в элемент управления контейнера, контейнер вызывает все события добавленного элемента управления до тех пор, пока он не догонит текущее событие.Однако добавленный элемент управления не догоняет обратную обработку данных.Чтобы добавленный элемент управления участвовал в обработке данных обратной передачи, включая проверку, элемент управления должен быть добавлен в событии Init, а не в событии Load.

Следовательно, не следует ли LoadControl корректно инициализировать элемент управления?

Редактировать:

Хорошо, итак, я отвечаю здесь на свой собственный вопрос ..

Я нашел ответную версию сообщения на форуме, на которое я ссылался выше Здесь

По сути, ответ заключается в том, что LoadControl( type, params ) не удается вывести ascx-код 'page infront' для синтаксического анализа, и, следовательно, он не утруждает себя инициализацией какого-либо из элементов управления.Когда вы используете LoadControl( "ascx path" ) версия ему присваивается страница infront и, следовательно, выполняет весь синтаксический анализ и инициализацию.

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

Control ErrorCntrl = LoadControl("ErrorDisplay.ascx");
ErrorCntrl.ID = SomeID;
(ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail;
divErrorContainer.Controls.Add(ErrorCntrl);

И это должно сработать нормально..Это не так аккуратно, как моя предыдущая попытка, но, по крайней мере, это сработает.

Я по-прежнему открыт для предложений по улучшению вышесказанного.

Ваше здоровье

Другие советы

Соглашаясь с Митчелом, вы должны иметь возможность поместить page_load в сам код элемента управления, который будет запускаться после того, как элементы управления будут полностью доступны.

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

Рад, что вы нашли ответ на свой вопрос!

Здесь это запись в блоге, написанная Стивеном Роббинсом.В этом сообщении объясняется, как передать параметры для пользовательского элемента управления с помощью LoadControl, подобный тому , что LoadControl(Type, object[]) сделал бы, за исключением того, что это работает :)

У меня была аналогичная проблема с событием dayRender для управления календарем, поскольку я хотел добавить пользовательский элемент управления в e.Cell.Коллекция элементов управления.Попробовав пару неудачных подходов, когда пользовательский элемент управления page_load не запускался или listbox в ascx выдавал исключение null, я обнаружил, что если я инициализирую свой элемент управления в форме с помощью LoadControl (ascx), а затем начинаю получать доступ к элементам управления разметкой в ascx, все работает нормально.Этот подход вообще не зависит от события Page_Load в ascx.

Разметка в формате ASCX

код, стоящий за

Открытый класс CPCalendarCell Наследует System.Web.UI.UserControl

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

End Sub

Public Sub Add(txt As String)
    Dim li As New ListItem(txt, txt)
    lstDay.Items.Add(li)
End Sub

Конечный Класс

ASPX- разметка страницы

код, стоящий за событием календаря dayRender в форме

Private Sub Calendar1_DayRender(sender As Object, e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender
    Dim div As CPCalendarCell = LoadControl("~/UserControls/CPCalendarCell.ascx")
    div.ID = "dv_" & e.Day.Date.ToShortDateString.Replace(" ", "_")

    **e.Cell.Controls.Add(div)**

    div.Add(e.Day.Date.Month.ToString & "/" & e.Day.Date.Day.ToString)
    div.Add("Item 1")
    div.Add("Item 2")
    e.Cell.Style.Add("background-color", IIf(e.Day.IsWeekend, "whitesmoke", "white").ToString)
End Sub

В соответствии с жизненным циклом страницы asp.net ваши элементы управления не полностью добавлены при предварительном рендеринге, почему бы вам просто не загрузить значения в page_load?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top