Telerik RadListView внутри панели обновления asp.net не обновляется

Последние пару дней я бился головой об стену, пытаясь заставить этот сценарий сработать.

у меня есть <asp:UpdatePanel> на странице, которая имеет внешний триггер и содержит Telerik RadListView:

<asp:UpdatePanel runat="server" ID="RationUpdatePanel" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
    <telerik:RadListView ID="RationListView runat="server"
        DataSourceId="RationDataSource" 
        OnItemCanceling="ItemCancelingHandler"
        OnItemEditing="ItemEditingHandler"
        OnItemUpdating="ItemUpdateHandler">
        <LayoutTemplate>
            <table>
               <thead>
                   <tr>...</tr>
               </thead>
               <tbody>
                   <tr id="itemPlaceHolder" runat="server"/>
               </tbody>
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <tr>
               <td>
                   <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit" ToolTip="Edit" />&nbsp;
                   <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete" ToolTip="Delete" />
               </td>
               <td>...</td>
             </tr>
        </ItemTemplate>
        <EditItemTemplate>
            <tr>
               <td>
                   <asp:LinkButton ID="SaveButton" runat="server" CausesValidation="False" CommandName="Save" Text="Save" ToolTip="Save" />&nbsp;
                   <asp:LinkButton ID="CancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel" ToolTip="Update" />
               </td>
               <td>...</td>
             </tr>
        </EditItemTemplate>
    </telerik:RadListView>
</ContentTemplate>
<Triggers>
    <asp:AsyncPostBackTrigger ControlID="UseRationButton" EventName="Click" />
</Triggers>
</UpdatePanel>

Код позади выглядит так:

    protected void RationListView_ItemEditing(object sender, RadListViewCommandEventArgs e)
    {
        ((RadListViewDataItem)e.ListViewItem).Edit = true;
    }

    protected void RationListView_ItemCanceling(object sender, RadListViewCommandEventArgs e)
    {
        RationListView.ClearEditItems();
        ((RadListViewDataItem)e.ListViewItem).Edit = false;
    }

Нажав на EditButton или же CancelButton произвел ожидаемые события и вызывается подпрограмма ObjectDataSource для перепривязки списка, но панель обновления не обновляется. призвание RationUpdatePanel.Update() От обработчиков событий ситуация не меняется. Код работает правильно за пределами панели обновления: режим меняется, и отображаются кнопки из другого шаблона.

В любом случае нажатие на внешний триггер приводит к отображению списка.

Обновление: я добавил пару обратных вызовов javascript к классу PageManager в браузере для beginRequest и endRequest. Они просто отображают предупреждение, когда происходит событие.

Страница содержит несколько элементов, которые в основном выглядят так (детали опущены):

<div>
    <div>
        <asp:DropDownList ID="RationDdl"/>
        <asp:Button ID="UseRationButton"/>
    </div>
    <div>
        <asp:DropDownList ID="AnimalGroupDdl"/>
        <asp:UpdatePanel ID="AnimalWeightUpdatePanel"/>
            <ContentTemplate>
                <asp:DropDownList ID="AnimalWeightDdl"/>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
</div>
<div>
    <telerik:RadListBox>
    </telerik:RadListBox>
</div>
<div>
    <asp:UpdatePanel ID="FeedPreviewUpdatePanel">
        <ContentTemplate>
            <asp:Repeater>
            </asp:Repeater>
        </ContentPanel>
    </asp:UpdatePanel>
</div>  
<div>
    <!-- this contains the update panel shown above -->
</div>

UseFeedRationButton в первом div это внешний триггер для RationUpdatePanel, AnimalGroupDdl является внешним триггером для AnimalWeightUpdatePanel, Обработчик события SelectedIndexChanged на AnimalGroupDdl заполняет AnimalWeightDdl с доступными весовыми категориями для выбранной группы. Не имеет никакого взаимодействия с RationUpdatePanel или же FeedPreviewUpdatePanel,

Вот разметка для UseRationButton:

            <asp:Button ID="UseRationButton" runat="server" 
                Text="Use This Ration" 
                OnClick="UseRationButton_Click" 
                CausesValidation="true" 
                ValidationGroup="UseRation" 
                UseSubmitBehavior="false">
            </asp:Button>&nbsp;

И вот код позади:

    protected void UseRationButton_Click(object sender, EventArgs e)
    {
        string text = this.RationDdl.SelectedItem.Text;
        this.RationNameLabel.Text = text;
        this.RationDataSource.SelectParameters["RationId"].DefaultValue = this.RationDdl.SelectedValue;
    }

Есть два сценария, которые я тестировал:

1) Выберите рацион из RationDdl и нажмите UseRationButton2) Выберите группу животных и выполните сценарий 1.

В сценарии 1 асинхронная обратная передача инициируется клиентским кодом asp.net, а событие кнопки обрабатывается на стороне сервера. RationListView заполнен, но код endRequest на стороне клиента никогда не выполняется (предупреждение не отображается). Последующие щелчки на элементах управления в RadListView вызывают асинхронную обратную передачу, но состояние списка не изменяется, и код endRequest на стороне клиента не выполняется.

В сценарии 2 инициируется асинхронная обратная передача, событие обрабатывается на стороне сервера и AnimalWeightDdl населён. В этом случае выполняется код endRequest на стороне клиента (отображается предупреждение IS). После этого выбор нормы и нажатие на кнопку использования порции инициирует обратную передачу, заполняется представление списка и выполняется код endRequest. В этот момент нажатие на кнопки в представлении списка приводит к инициированию асинхронной обратной передачи, изменению состояния списка и выполнению кода endRequest.

Моя рабочая теория заключается в том, что что-то приводит к тому, что состояние класса диспетчера запросов страниц на клиенте становится неопределенным, но я не могу понять, что может быть причиной этого.

2 ответа

Решение

Исследование, которое я провел поздно вечером в пятницу и субботу, дало ответ на этот вопрос.

У меня был некоторый код, прикрепленный к Sys.WebForms.PageRequestManager Событие endRequest, которое обновило текстовое поле, которое содержало временный заголовок для нового рациона. Код выглядел так:

    ///
    /// reregister the change handlers after reloading the animal weight ddl and create a 
    /// temporary name for the ration based on animal choice and weight.
    ///
    function animalWeightDdlOnLoad() {
        var ddl = document.getElementById("<%= AnimalWeightDdl.ClientID %>");

        //
        // add event handler in a browser agnostic fashion
        //
        if (ddl.addEventListener) {
            ddl.addEventListener("change", animalWeightDdlOnChange);
        }
        else if (ddl.attachEvent) {
            ddl.attachEvent("onchange", animalWeightDdlOnChange);
        }
        else {
            ddl.onchange = animalWeightDdlOnChange;
        }

        animalWeightDdlOnChange();
    }

animalWeightDdlOnChange() Ссылка на список параметров веса животных ddl:

    ///
    /// create a temporary name for the ration
    ///
    function animalWeightDdlOnChange() {
        var ddl1 = document.getElementById("<%= AnimalGroupDdl.ClientID %>");
        var ddl2 = document.getElementById("<%= AnimalWeightDdl.ClientID %>");
        var text = document.getElementById("<%= RationNameText.ClientID %>");
        text.value = ddl1.options[ddl1.selectedIndex].text + ' ' + ddl2.options[ddl2.selectedIndex].text + ' - Copy';
    }

Однако, если список еще не был заполнен, ссылка на опции вызвала ошибку, которая остановила обработку endRequest. Вместо того чтобы запускать этот код при каждом асинхронном запросе, я изменил его на обработчик события change в группе животных ddl, например:

    function animalGroupDdlOnSelectedChanged() {
        //
        // add a handler for the endRequest event which will be triggered by
        // fetching the contents of the weight ddl.
        //
                         Sys.WebForms.PageRequestManager.getInstance().add_endRequest(animalWeightDdlOnLoad);
    }

Затем в animalWeightDdlOnLoad() Я добавил строку, чтобы удалить обработчик после выполнения запроса. Это гарантировало, что обработчик изменений для веса ddl будет работать только после заполнения списка. Задача решена. Но на всякий случай я добавил проверку длины списка опций ddl для веса животных.

Так что даже на первый взгляд невинный JavaScript может испортить обработку вашего асинхронного запроса в браузере.

Во-первых, если вы используете Telerik Rad Control, я предлагаю вам изменить asp:button в telerik:RadButton,
Вот пример

  <telerik:RadButton ID="v" runat="server" Text="Use This Ration"
         AutoPostBack="true" 
  ValidationGroup="UseRation" OnClick="UseRationButton_Click">
  </telerik:RadButton>


  protected void UseRationButton_Click(object sender, EventArgs e)
    {
     string text = this.RationDdl.SelectedItem.Text;
    this.RationNameLabel.Text = text;
    this.RationDataSource.SelectParameters["RationId"].DefaultValue = this.RationDdl.SelectedValue;
    }

Обратите внимание, что вы должны добавить AutoPostBack="true" в вашем RadButton .
И эти ссылки, MSDN Reference1 и MSDN Reference2 покажут детали использования панели обновления.

Другие вопросы по тегам