2009-08-22 85 views
2

我有下面的代碼。我試圖創建一個嚮導類型的接口,動態加載用戶控件,動態加載每個步驟的控件。每一步都有一個按鈕來引發一個事件。父頁面應該加載嚮導中的下一個控件。發生的事情是同一個控件連續呈現兩次,使我點擊按鈕兩次。嚮導中的動態加載控件

我需要另一組眼睛來看代碼。

public partial class CreateTriviaGame : BasePage 
    { 
     private TriviaGame _game; 
     private int _step = 1; 

     protected void Page_PreLoad(object sender, EventArgs e) 
     { 
      LoadStepControl(); 
     } 

     private void LoadStepControl() 
     {   
      BaseTriviaGameControl ctrl = null; 
      switch (_step) 
      { 
       case 1: 
        ctrl = (BaseTriviaGameControl)LoadControl("AddEditGame.ascx"); 
        break; 
       case 2: 
        ctrl = (BaseTriviaGameControl)LoadControl("CrudQuestions.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 3: 
        ctrl = (BaseTriviaGameControl)LoadControl("AddEditPaymentInfo.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 4: 
        ctrl = (BaseTriviaGameControl)LoadControl("ConfirmPayment.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 5: 
        ctrl = (BaseTriviaGameControl)LoadControl("ThankForPayment.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
      } 

      ctrl.EntitySaved += new EventHandler(ctrl_EntitySaved); 
      holder1.Controls.Add(ctrl); 

     } 

     protected void ctrl_EntitySaved(object sender, EventArgs e) 
     { 
      _game = ((BaseTriviaGameControl)sender).TriviaGame; 
      _step++; 
      holder1.Controls.Clear(); 
      LoadStepControl(); 
     } 

     protected override void LoadViewState(object savedState) 
     { 
      base.LoadViewState(savedState); 
      _game = (TriviaGame)ViewState["Game"]; 
      _step = (int)ViewState["Step"]; 
     } 

     protected override object SaveViewState() 
     { 
      ViewState["Game"] = _game; 
      ViewState["Step"] = _step; 
      return base.SaveViewState();   
     } 


    } 

**編輯** 我要補充一點,我做它像這種情況的原因是避免以聲明的所有控件添加到頁面中,然後對付他們每個人的面前裝他們需要加載。

回答

1

使用Page_Init或Page_PreInit事件。

+0

您不能使用這些事件。它們在視圖狀態被反序列化之前觸發。我不知道我在處理什麼控制。 – Darthg8r 2009-08-22 04:31:48

+0

此外,所用的佔位符還未被初始化。 – Darthg8r 2009-08-22 04:33:01

+0

我也嘗試過使用InitComplete。雖然我有viewstate和一個佔位符,但它仍然有一個我無法處理的行爲。點擊按鈕,第2步顯示,點擊按鈕,第1步顯示,點擊按鈕,第3步顯示,點擊,第1步,點擊第4步。 – Darthg8r 2009-08-22 04:43:17

1

這個設置很奇怪。

我的第一個建議是在LoadStepControl()過程中爲你的控件顯式分配一個ID,這樣無論控件是什麼,它都有相同的ID。這可能會幫助丟失事件處理程序。我猜在事件處理程序中,當你清除佔位符並添加一個新的控件時,它會以比PreLoad()中第一次添加的方式獲得不同的ID。因此,ID之間不匹配回傳,所以沒有事件處理程序可以找到。

我的第二個建議是重新使用您的方法,並將所有控件靜態添加到頁面,並將其可見性設置爲false。除非你真的有一個可衡量的性能問題,這將爲您節省大量的麻煩,而且我用您在那裏得到的那種代碼的經驗來講;)

我的第三個建議是看看使用ASP.Net Wizard control

+0

我同意這些事件可能會下降。在處理動態添加的控件時,最好的辦法是將它們放回頁面並重新連接* Init()事件之一的事件,以便控件在事件循環中存在。 我也同意,只要打開和關閉的東西可能是一種方式去除非採取全面的重新考慮。使用目前的方法,頁面必須知道所有的控件,所以我沒有看到試圖動態交換它們的好處。如果控件/步驟正在從數據庫中讀出,那麼這將是適當的。 – 2009-08-22 06:09:56

+0

...繼續在HTML和cs文件中的控件,但關閉它們不會導致任何真正的開銷,只要你不做任何事情。 – 2009-08-22 06:16:32

1

我把你的方法評論Womp的答案。然而,當人們試圖忽視我的方法時,我個人討厭它,因爲他們沒有看到我想要做的事情的完整背景。如果是這種情況,我會推薦一種可能的解決方案來解決您當前的方法

  1. 將該步驟存儲在會話或查詢字符串中,以便在頁面生命週期的init方法期間保存該步驟。在解決等待視圖狀態負載的問題之前,您將無法解決Womp提出的事件的問題。
  2. 在頁面的OnInit或PreInit事件期間,始終將控件添加到佔位符以獲取每次回發中的當前步驟值。此外,請確保您在此時重新舉辦活動。在視圖狀態加載之前,您必須在每次加載時執行此操作。這對確保持有者中的控件正確初始化至關重要。
  3. 遞增步驟並觸發控件交換,就像您現在在事件處理程序中執行的那樣(因爲您每次在事件生命週期之前都將控件重新放回頁面,現在將始終正確啓動)。

示例:首次加載頁面時,您將AddEditGame.ascx控件放入持有者中,並在OnInit期間連接事件。當用戶重新發布帖子時,您將再次將AddEditGame.ascx控件放入持有者中,並連接事件,以便引發事件的控件(AddEditGame.ascx)將位於事件週期的控件樹中。處理完該事件後,您可以增加該步驟並觸發控件交換,將CrudQuestions.ascx放入持有者中,並連接其事件。當用戶發回帖子時,你會在初始化期間將CrudQuestions.ascx放入佔位符中,等等......

最大的變化是你不必依賴等待viewstate加載要知道你在做什麼步驟,並且通過在事件週期發生之前放置導致回發回到頁面上的控件,使事件正確觸發。

我希望這是有道理的/幫助。