Asp.net Usercontrol LoadControl Issue
У меня возникает проблема при использовании 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" />
с кодом (С#) за:
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, переменные lblTitle и lblDescription оба null
, несмотря на то, что они имеют эквивалент разметки. Переменная сообщения была правильно заполнена.
Может ли кто-нибудь пролить свет на то, почему это может произойти?
Спасибо
EDIT:
Просто для ясности я также добавлю, что код, который программно добавляет usercontrol на страницу, запускается в ответ на нажатие кнопки, поэтому "хостинг-страница" продвигается через Init, Page_Load и теперь обрабатывает событие обработчики.
Я не могу добавить usercontrols на более ранний этап жизненного цикла asp, поскольку они создаются в ответ на событие нажатия кнопки.
Ответы
Ответ 1
Я тоже пробовал следующий код - который дает тот же результат (т.е. оба lblTitle и lblDescription равны нулю)
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 инициализировать элемент управления?
EDIT:
Хорошо, поэтому я отвечаю на свой вопрос здесь.
Я нашел ответную версию сообщения форума, с которым я связан выше Здесь
По сути, ответ заключается в том, что LoadControl( type, params )
не может вывести "ascront" ascx для синтаксического анализа и, следовательно, он не беспокоит инициализацию какого-либо элемента управления. Когда вы используете версию LoadControl( "ascx path" )
, ей предоставляется страница infront и, следовательно, все синтаксические разборки и initalision.
Итак, я должен изменить код, который инициализирует элемент управления и разбивает его на отдельные части. То есть.
Control ErrorCntrl = LoadControl("ErrorDisplay.ascx");
ErrorCntrl.ID = SomeID;
(ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail;
divErrorContainer.Controls.Add(ErrorCntrl);
И он должен работать нормально.. Это не так хорошо, как моя предыдущая попытка, но, по крайней мере, это сработает.
Я по-прежнему открыт для предложений по улучшению выше.
Приветствия
Ответ 2
Соглашаясь с Mitchel, вы должны иметь возможность поставить page_load в сам код управления, который будет срабатывать после того, как элементы управления будут полностью доступны.
Ответ 3
Хорошо всегда добавляется ваше собственное событие загрузки и вызывается после запуска конструктора и добавляется элемент управления на страницу, но он не сильно отличается от того, что у вас есть, хотя я могу выбрать его по причинам стиля.
Рад, что вы нашли ответ на свой вопрос!
Ответ 4
Здесь - это сообщение в блоге, написанное Стивеном Роббинсом. Сообщение объясняет, как передать параметры для пользовательского элемента управления с помощью LoadControl
, аналогично тому, что будет делать LoadControl(Type, object[])
, , за исключением того, что оно работает:)
Ответ 5
У меня была аналогичная проблема с событием DayRender Calendar control, в котором я хотел добавить элемент управления пользователя в коллекцию e.Cell.Controls. Попробовав пару неудачных подходов с пользовательским контролем page_load, не запускающим или списком на ascx, бросающим нулевое исключение, я обнаружил, что если бы я инициализировал свой контроль над формой с помощью 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
Ответ 6
В жизненном цикле страницы asp.net ваши элементы управления не полностью добавляются в предварительную визуализацию, почему бы вам просто не загружать значения в page_load?