Asp.NET пользовательский обработчик событий управления сервером не запускается при второй обратной передаче

#c# #asp.net #postback #sitecore #custom-server-controls

#c# #asp.net #обратная передача #sitecore #пользовательские серверные элементы управления

Вопрос:

Я разрабатываю пользовательский серверный элемент управления в Asp.NET (.NET 3.5), который наследует класс CompositeControl. Внутри моего элемента управления я переопределяю CreateChildControls() метод для генерации смеси html и Asp.NET серверные элементы управления. Некоторые из Asp.NET добавляемые элементы управления — это LinkButton s (для каждого из которых установлен свой Command обработчик событий, соответствующий методу, находящемуся под моим контролем). Я обнаружил, что при первом нажатии одной из этих кнопок LinkButtons запускается обратная передача, и метод обработчика событий запускается правильно. Внутри этого обработчика событий явно вызывается метод CreateChildControls() для регенерации элемента управления в ответ на обратную передачу. Затем я обнаруживаю, что последующие нажатия на LinkButton s обратных отправлений не приводят к запуску метода обработчика событий.

Я предполагаю, что способ, которым я обрабатываю регенерацию элемента управления при обратной передаче, должен быть неисправен, но я не могу понять, что делать — я осознаю тот факт, что при этой первой обратной передаче CreateChildControls () вызывается дважды, что, вероятно, не идеально, но поскольку CreateChildControls вызывается до возникновения каких-либо событий, я не вижу способа обойти это.

Упрощенная версия моего класса управления показана ниже:

 public class SearchResults : CompositeControl
{
    private int PageIndex = 0;

    protected override void CreateChildControls()
    {
            //do stuff here e.g.
            LinkButton prevLink = new LinkButton();
            prevLink.Text = "< Prev";
            prevLink.CommandArgument = (PageIndex - 1).ToString();
            prevLink.Command  = new CommandEventHandler(PagerLinkCommand);
            this.Controls.Add(prevLink);
    }

    protected void PagerLinkCommand(object sender, CommandEventArgs e)
    {
        PageIndex = int.Parse(e.CommandArgument.ToString());
        CreateChildControls();
    }
}
  

Редактировать
Проблема здесь была вызвана тем фактом, что элемент управления используется на сайте Sitecore, и я забыл зарегистрировать тип элемента управления в файле web.config с <typesThatShouldNotBeExpanded> записью. Эта запись используется для предотвращения того, чтобы серверные элементы управления не перепутали свои события Sitecore — это может вызвать аналогичные проблемы для стандартных серверных элементов управления, таких как ListView, GridView и Repeater и т.д. Мой web.config был изменен, как показано ниже:

   <typesThatShouldNotBeExpanded>
    <type>System.Web.UI.WebControls.Repeater</type>
    <type>System.Web.UI.WebControls.DataList</type>
    <type>System.Web.UI.WebControls.GridView</type>
    <type>MyNamespace.MyCustomControl</type> <!-- This is the bit I added -->
  </typesThatShouldNotBeExpanded>
  

Комментарии:

1. Базовый класс должен вызвать CreateChildControls() для вас — попробуйте удалить его.

Ответ №1:

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

 LinkButton prevLink = new LinkButton();
prevLink.ID = "prevLink";
  

Комментарии:

1. вы сделали это для всех сгенерированных элементов управления в методе CreateChildControls()? В частности, элементы управления, в которые вложен LinkButton.

2. Я нашел эту статью v полезной: singingeels.com/Articles /…

Ответ №2:

Извиняюсь… это не полный ответ, а предложение по отладке, которое слишком длинно для комментария:

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

Двумя абсолютными ключами к успешному динамически создаваемому элементу управления являются
1) Создание их в нужное время в течение жизненного цикла страницы
2) Повторное создание ТОЧНО ТАКОЙ ЖЕ иерархии элементов управления (включая идентификаторы) при обратной передаче

Ответ №3:

Чтобы получить правильное дерево управления, переопределите свойство Controls и вызовите EnsureChildControls, а также вызовите EnsureChildControls, а не CreateChildControls внутри команды PagerLinkCommand.

     /// <summary>
    /// Gets controls.
    /// </summary>
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return base.Controls;
        }
    }

    /// <summary>
    /// Create child controls.
    /// </summary>
    protected override void CreateChildControls()
    {
        this.Controls.Clear();
        //do stuff here e.g.
        LinkButton prevLink = new LinkButton();
        prevLink.Text = "< Prev";
        prevLink.CommandArgument = (PageIndex - 1).ToString();
        prevLink.Command  = new CommandEventHandler(PagerLinkCommand);
        this.Controls.Add(prevLink);
    }

    protected void PagerLinkCommand(object sender, CommandEventArgs e)
    {
      PageIndex = int.Parse(e.CommandArgument.ToString());
      EnsureChildControls();
    }        
  

Комментарии:

1. К сожалению, это, похоже, не помогает. CreateChildControls() теперь не вызывается после PagerLinkCommand().

2. не забудьте вызвать base. CreateChildControls() внутри CreateChildControls()

Ответ №4:

Причина такого поведения заключалась не в самом серверном элементе управления, а была связана с Sitecore. Для того, чтобы Sitecore не мешал обратным отправкам управления сервером, необходимо добавить запись в typesThatShouldNotBeExpanded раздел файла web.config, как показано ниже.

 <typesThatShouldNotBeExpanded>
  <type>System.Web.UI.WebControls.Repeater</type>
  <type>System.Web.UI.WebControls.DataList</type>
  <type>System.Web.UI.WebControls.GridView</type>
  <type>MyNamespace.MyCustomControl</type> <!-- This is the bit I added -->
</typesThatShouldNotBeExpanded>