2009-08-22 86 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加载要知道你在做什么步骤,并且通过在事件周期发生之前放置导致回发回到页面上的控件,使事件正确触发。

我希望这是有道理的/帮助。