Приносим извинения за отправку столь длинного вопроса. Верьте или нет, то, что вы видите здесь, фактически представляет собой довольно сжатую версию проблемы/кода под рукой. И хотя я был бы признателен за любые указатели на лучший или другой подход, я также очень хотел бы получить дно этого, чтобы я мог спать по ночам :)Загрузка элементов управления за пределы Page_Load - нет-нет?
Я столкнулся с требованием передать подтверждающие сообщения между отдельными aspx pages. Я отказался от использования переменной строки запроса, поскольку значения строки запроса «являются липкими (т. Е. Они сохраняются во всех последующих обратных передачах), и я не хотел иметь дело с добавлением кучи условной логики вокруг этого.
В любом случае, я создал очень простой класс, который использует Session для связывания уведомлений с определенными URL-адресами. Затем я подключил свою главную страницу Page_Load событие для запроса этого класса для любых уведомлений, которые должны отображаться для текущего URL-адреса. Если он находит что-либо, он динамически загружает пользовательский элемент управления NotificationMessage и отображает содержимое сообщения.
Все работает как ожидается при попытке передать Уведомления между различными страницами aspx. Как и ожидалось, все не работает, когда страница контента пытается добавить уведомление самому себе (т. Е. «Введенные данные недействительны, повторите попытку»). Причина довольно ясна: к тому моменту, когда страница контента добавляет уведомление для себя, событие главной страницы уже запущено, поэтому слишком поздно на жизненном цикле страницы сделать что-то хорошее. Соответствующий код будет вставлен ниже.
public class MyMasterPage:MasterPage{
protected void Page_Load(object sender, EventArgs e)
{
LoadNotifications(this.Request.Url.ToString());
}
private void LoadNotifications(string url)
{
//look for a notification
Notification? notification = NotificationManager.Instance.RetrieveNotification(url);
//there are no notifications, nothing to see here
if (!notification.HasValue)
{
return;
}
//there is a Notification for this url, so load it into a user control
NotificationMessage notificationMessageControl = (NotificationMessage)LoadControl("~/App_UserControls/NotificationMessage.ascx");
notificationMessageControl.ID = "notificationMessage";
notificationMessageControl.Notification = notification;
notificationMessageControl.Visible = true;
//find the placeholder on the master page
PlaceHolder placeHolder = (PlaceHolder)PageUtils.FindControlRecursive(this, "NotificationPlaceholder");
if (placeHolder == null)
{
throw new ApplicationException("NotificationPlaceholder control not found.");
}
//insert into control
placeHolder.Controls.Add(notificationMessageControl);
placeHolder.Visible = true;
//remove the notification so it doesn't show up next time
NotificationManager.Instance.RemoveNotification(url);
}
}
Учитывая жизненный цикл, выпущенные уже упоминалось выше, я изменил класс NotificationManager так, что это вызывает событие, когда уведомление было добавлено для текущей страницы. Основная страница перехватывает это событие, и если Page_Load уже запущен, он снова запускает метод LoadNotifications.
//bind the event on the page constructor
public MyMasterPage()
{
NotificationManager.Instance.NotificationAdded += this.NotificationAdded;
}
private void NotificationAdded(string forUrl)
{
if (_pageLoaded){
LoadNotifications(forUrl);
}
}
К сожалению, это не работает. Я многократно перешагивал этот код и, несмотря на то, что главная страница загружает NotificationMessage UserControl и добавляет ее к соответствующему заполнителю без инцидентов, окончательный aspx HTML never включает разметку для этого UserControl. Я установил контрольные точки внутри Page_Load UserControl и проверил, что они действительно попадают во время выполнения.
Если я динамически загружать UserControl внутри страницы содержимого и обойти страницу Master в целом, это делает без задоринки:
public partial class MyContentPage:Page
{
public void DoSomethingCool(object sender, EventArgs e)
{
if (MyServiceLayer.Save(foo)==false){
Notification notification = new Notification(NotificationType.Error, "We’re sorry, your document was not saved.");
NotificationMessage notificationMessage = (NotificationMessage)LoadControl("~/App_UserControls/NotificationMessage.ascx");
notificationMessage.Notification = notification;
notificationMessage.Visible = true;
PlaceHolder holder = (PlaceHolder)PageUtils.FindControlRecursive(this, "NotificationPlaceholder");
holder.Controls.Add(notificationMessage);
}
}
}
Для записи, я раздели динамическую загрузку UserControl, выбор вместо этого для статической декларации в разметке главной страницы и кода, основанного на переключении свойства Visible элемента управления; все еще нет кубиков!
Если кто-то может пролить свет на эту загадку, я был бы очень обязан.
+1 за хороший дизайн – David
Звучит интригующе. Не могли бы вы подробно остановиться на примере? –