2009-08-25 12 views
0

Приносим извинения за отправку столь длинного вопроса. Верьте или нет, то, что вы видите здесь, фактически представляет собой довольно сжатую версию проблемы/кода под рукой. И хотя я был бы признателен за любые указатели на лучший или другой подход, я также очень хотел бы получить дно этого, чтобы я мог спать по ночам :)Загрузка элементов управления за пределы 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 элемента управления; все еще нет кубиков!

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

ответ

2

Я раньше пробовал такие вещи, и я никогда не был полностью в этом уверен. Вместо этого я поставил свой ASCX на каждую страницу (или на главную страницу) и позволил ASCX управлять своим состоянием, а не позволять ASPX управлять моим ASCX.

Я не уверен, что это поможет вам в вашей ситуации.

+0

+1 за хороший дизайн – David

+0

Звучит интригующе. Не могли бы вы подробно остановиться на примере? –

1

Кажется, что вы хотите, чтобы ваша информация появилась после того, как вы стреляли из контрольных событий. Вы можете подумать о том, чтобы эти сообщения были объединены до тех пор, пока все события управления не будут запущены, а затем вытащите все сообщения из вашего NotificationManager в OnPreRender, а не Page_Load. Таким образом, вы можете избавиться от событий (например, NotificationAdded) и т. Д., Которые, вероятно, усложняют ситуацию.

Не проблема на 100%, но проблема. Иногда это помогает понять, что MasterPage на самом деле является контролем на странице, а не наоборот, как вы думаете. Он будет подвергаться ограничениям, которые любой элемент управления будет иметь на странице.

НТН, Андерсон

Смежные вопросы