【问题标题】:How can I create buttons and hook up events from postback如何从回发创建按钮和连接事件
【发布时间】:2010-09-21 08:05:41
【问题描述】:

我最初需要基于相当多的处理器和磁盘密集型搜索来生成按钮。每个按钮将代表一个选择并触发回发。我的问题是回发不会触发命令 b_Command。我猜是因为原始按钮尚未重新创建。我无法在回发中执行原始搜索以重新创建按钮,所以我想从回发信息中生成所需的按钮。

我应该如何以及在哪里执行此操作?例如,我应该在 Page_Load 之前这样做吗?如何从回发中重建 CommandEventHandler - 如果有的话?

   namespace CloudNavigation
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                // how can I re-generate the button and hook up the event here
                // without executing heavy search 1
            }
            else
            {
                // Execute heavy search 1 to generate buttons
                Button b = new Button();
                b.Text = "Selection 1";
                b.Command += new CommandEventHandler(b_Command);
                Panel1.Controls.Add(b);
            }
        }

        void b_Command(object sender, CommandEventArgs e)
        {
            // Execute heavy search 2 to generate new buttons
            Button b2 = new Button();
            b2.Text = "Selection 2";
            b2.Command += new CommandEventHandler(b_Command);
            Panel1.Controls.Add(b2);
        }
    }
}

【问题讨论】:

    标签: c# .net asp.net events postback


    【解决方案1】:

    您的 ASPX 是否已连接事件处理程序?

    <asp:Button id="btnCommand" runat="server" onClick="b_Command" text="Submit" />
    

    【讨论】:

      【解决方案2】:

      需要在加载事件之前创建按钮,否则状态将无法正确连接。而是在 Init() 中重新创建按钮。

      至于如何在不重新运行搜索的情况下执行此操作,我建议您将结果缓存在某处。缓存中存在结果集是您在 Init() 事件中的按钮代码如何知道它需要运行的方式。

      或者,您可以将按钮静态放置在页面上。只要放足够的东西来处理搜索返回的任何内容。如果您认为这可能是方式太多的项目,那么问问你自己:你的用户真的想要对这么多项目进行排序吗?也许您应该考虑分页这些数据,在这种情况下,静态按钮不再那么重要了。

      【讨论】:

        【解决方案3】:

        我同意 Joel 关于缓存搜索结果的观点。至于按钮,您可以在页面生命周期的初始化或加载阶段动态创建它们,但请注意,如果您删除一个按钮,然后以编程方式将其添加回来,您会弄乱您的状态。

        在我的一个项目中,我们有一个动态表单,可以即时生成字段,我们使其工作的方式是通过存储在缓存或页面视图状态中的数组。该数组包含要显示的按钮,并在每个页面加载时重新创建按钮,以便可以将状态正确加载到其中。然后,如果我需要更多按钮或一组全新的按钮,我会在数组中标记隐藏值,并在数组中为新的一组相应按钮添加一组新值。这样状态不会丢失,按钮继续工作。

        如果您以编程方式创建按钮,您还需要确保为按钮的 on_click 事件添加处理程序,我想我在顶部的代码中可以看到。

        【讨论】:

          【解决方案4】:

          当回发事件处理试图找到它在集合中不存在的控件时会发生什么。 结帐 Denis DynamicControlsPlaceholder @http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx

          希望对你有帮助 布鲁诺·菲格雷多 http://www.brunofigueiredo.com

          【讨论】:

            【解决方案5】:

            这是一个带有自定义视图状态处理的示例(注意按钮有EnableViewState = false):

                protected void Page_Load(object sender, EventArgs e)
                {
                    if (!IsPostBack)
                    {
                        // Execute heavy search 1 to generate buttons
                        ButtonTexts = new ButtonState[] { 
                            new ButtonState() { ID = "Btn1", Text = "Selection 1" } 
                        };
                    }
                    AddButtons();
                }
            
                void b_Command(object sender, CommandEventArgs e)
                {
                    TextBox1.Text = ((Button)sender).Text;
            
                    // Execute heavy search 2 to generate new buttons
                    ButtonTexts = new ButtonState[] { 
                        new ButtonState() { ID = "Btn1", Text = "Selection 1" }, 
                        new ButtonState() { ID = "Btn2", Text = "Selection 2" } 
                    };
                    AddButtons();
                }
            
                private void AddButtons()
                {
                    Panel1.Controls.Clear();
                    foreach (ButtonState buttonState in this.ButtonTexts)
                    {
                        Button b = new Button();
                        b.EnableViewState = false;
                        b.ID = buttonState.ID;
                        b.Text = buttonState.Text;
                        b.Command += new CommandEventHandler(b_Command);
                        Panel1.Controls.Add(b);
                    }
                }
            
                private ButtonState[] ButtonTexts
                {
                    get
                    {
                        ButtonState[] list = ViewState["ButtonTexts"] as ButtonState[];
                        if (list == null)
                            ButtonTexts = new ButtonState[0];
                        return list;
                    }
                    set { ViewState["ButtonTexts"] = value; }
                }
            
                [Serializable]
                class ButtonState
                {
                    public string ID { get; set; }
                    public string Text { get; set; }
                }
            

            【讨论】:

              【解决方案6】:

              没有执行 b_Command 事件处理程序方法,因为没有重新创建回发按钮(因为它们是动态生成的)。每次重新创建页面时,您都需要重新创建它们,但为了做到这一点,您需要在状态的某处显式缓存信息。

              如果这是一个页面范围的操作,最简单的方法是将其存储在 ViewState 中(作为字符串 - 如果您开始使用对象加载 ViewState,您将看到性能下降),以便您可以在下次加载时检查它(或任何其他先前的事件)并在重新加载页面时重新创建按钮。 如果操作是会话范围的,您可以轻松地将对象(数组或其他)存储在会话中,并在下一次加载(或初始化)时检索它以重新创建控件。

              这种情况意味着您只需在 b_Command EventHandler 中存储有关按钮的一些信息,而不是创建和添加按钮,因为如果这样做,您将在下一次回发中丢失相关信息(就像现在发生的那样)。

              所以你的代码会变成这样:

              namespace CloudNavigation
              {
                  public partial class Test : System.Web.UI.Page
                  {
                      protected void Page_Load(object sender, EventArgs e)
                      {
                          if (IsPostBack)
                          {
                              this.recreateButtons();
                          }
                          else
                          {
                              // Execute heavy search 1 to generate buttons
                              Button b = new Button();
                              b.Text = "Selection 1";
                              b.Command += new CommandEventHandler(b_Command);
                              Panel1.Controls.Add(b);
                              //store this stuff in ViewState for the very first time
                          }
                      }
              
                      void b_Command(object sender, CommandEventArgs e)
                      {
                          //Execute heavy search 2 to generate new buttons
                          //TODO: store data into ViewState or Session
                          //and maybe create some new buttons
                      }
              
                      void recreateButtons()
                      {
                          //retrieve data from ViewState or Session and create all the buttons
                          //wiring them up to eventHandler
                      }
                  }
              }
              

              如果您不想在页面加载时调用 recreateButtons,您可以在 PreLoad 或 Init 事件上执行它,我看不出有什么区别,因为您可以在任何地方访问 ViewState/Session 变量(在 Init viewstate未应用,但您可以访问它以重新创建动态按钮)。

              有人会讨厌这种解决方案,但据我所知,在服务器端保留状态数据的唯一方法是 ViewState - Session - Page.Transfer 或客户端饼干。

              【讨论】:

                猜你喜欢
                • 2021-12-18
                • 2017-08-25
                • 1970-01-01
                • 2016-10-01
                • 2011-11-08
                • 2016-01-11
                • 2017-05-22
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多