Как я могу создавать кнопки и подключать события от обратной передачи - PullRequest
6 голосов
/ 07 ноября 2008

Мне нужно генерировать кнопки, изначально основанные на довольно интенсивном поиске процессора и диска. Каждая кнопка представляет выбор и запускает обратную передачу. Моя проблема в том, что постбэк не вызывает команду 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);
        }
    }
}

Ответы [ 6 ]

5 голосов
/ 09 ноября 2008

Метод обработчика событий 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
        }
    }
}

Если вы не хотите вызывать restoreateButtons при загрузке страницы, вы можете сделать это в PreLoad или в событиях Init, я не вижу разницы, так как вы сможете получить доступ к переменным ViewState / Session везде (в представлении Init по состоянию не применяется, но вы можете получить к нему доступ для повторного создания динамических кнопок).

Кто-то возненавидит это решение, но, насколько мне известно, единственный способ сохранить данные состояния на стороне сервера - это ViewState - Сеанс - Page.Transfer или файлы cookie на стороне клиента.

1 голос
/ 07 ноября 2008

Что происходит, когда обработчик события обратной передачи пытается найти элемент управления, которого нет в коллекции. Оформить заказ Denis DynamicControlsPlaceholder @ http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx

Надеюсь, это поможет Бруно Фигейредо http://www.brunofigueiredo.com

1 голос
/ 07 ноября 2008

Кнопки должны быть созданы до события загрузки, иначе состояние не будет правильно настроено. Вместо этого заново создайте свои кнопки в Init ().

Что касается того, как сделать это без повторного запуска поиска, я предлагаю вам где-то кешировать результаты. Наличие результирующего набора в кэше - это то, как ваш код кнопки в событии Init () узнает, что он должен быть запущен.

В качестве альтернативы, вы можете разместить кнопки на странице статически. Просто положите достаточно, чтобы справиться с поиском. Если вы думаете, что, возможно, это будет способ слишком много элементов, спросите себя: действительно ли ваши пользователи захотят отсортировать такое количество элементов? Возможно, вам стоит рассмотреть подкачку этих данных, и в этом случае статические кнопки уже не так важны.

0 голосов
/ 07 ноября 2008

Вот пример с пользовательской обработкой состояния представления (обратите внимание, что кнопки имеют 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; }
    }
0 голосов
/ 07 ноября 2008

Я согласен с Джоэлом в отношении кеширования результатов поиска. Что касается кнопок, вы можете создавать их динамически на фазах инициализации или загрузки жизненного цикла страницы, но помните, что если вы удалите кнопку, а затем добавите ее программно, вы испортите свое состояние.

В одном из моих проектов у нас есть динамическая форма, которая генерирует поле на лету, и способ, которым мы заставляем его работать, - через массив, который хранится в кеше или в состоянии просмотра страницы. Массив содержит кнопки для отображения, и при каждой загрузке страницы он заново создает кнопки, чтобы в них можно было правильно загружать состояние. Затем, если мне нужно больше кнопок или целый новый набор, я отмечаю значение скрытия в массиве и добавляю новый набор значений в массив для нового набора соответствующих кнопок. Таким образом, состояние не теряется, и кнопки продолжают работать.

Вам также необходимо убедиться, что вы добавили обработчик для события on_click для своих кнопок, если вы создаете их программно, что, я думаю, я вижу в вашем коде вверху.

0 голосов
/ 07 ноября 2008

Есть ли в вашем ASPX обработчик событий?

<asp:Button id="btnCommand" runat="server" onClick="b_Command" text="Submit" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...