Telerik RadListView inside asp.net update panel does not refresh

2k views Asked by At

I've been banging my head against the wall for the last couple of days trying to get this scenario to work.

I have an <asp:UpdatePanel> on a page which has an external trigger and contains a 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>

Code behind looks like this:

    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;
    }

Clicking on the EditButton or CancelButton produced the expected events and the ObjectDataSource routine to rebind the list is called, yet the update panel is not refreshed. Calling RationUpdatePanel.Update() from the event handlers does not change the situation. The code works properly outside of an update panel: the mode changes and the buttons from the other template are displayed.

In either scenario clicking on the external trigger causes the list to be displayed.

Update: I added a couple of javascript callbacks to the PageManager class in the browser for beginRequest and endRequest. These just display an alert when the event occurs.

The page contains several elements which basically look like this (details omitted):

<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>

The UseFeedRationButton in the first div is an external trigger for the RationUpdatePanel. AnimalGroupDdl is an external trigger for AnimalWeightUpdatePanel. The handler for the SelectedIndexChanged event on AnimalGroupDdl populates AnimalWeightDdl with available weight classes for the selected group. It has no interaction with RationUpdatePanel or FeedPreviewUpdatePanel.

Here is the markup for UseRationButton:

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

And here is the code behind:

    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;
    }

There are two scenarios I have been testing:

1) Choose a ration from RationDdl and click UseRationButton 2) Choose an animal group and then execute scenario 1.

In scenario 1 an async postback is initiated by the client side asp.net code and the button event is handled server side. The RationListView is populated but the client side endRequest code is never executed (the alert is not displayed). Subsequent clicks on the controls in the RadListView trigger an async postback but the state of the list is not changed and the client side endRequest code is not executed.

In scenario 2 an async postback is initiated, the event is handled on the server side and AnimalWeightDdl is populated. The client side endRequest code is executed in this case (the alert IS displayed). Subsequent to this selecting a ration and clicking on the use ration button initiates a postback, the list view is populated and the endRequest code is executed. At his point clicking on buttons in the list view causes an async postback to be initiated, the state of the list is changed and the endRequest code is executed.

My working theory is that something is causing the state of the page request manager class on the client to become fubared, but I can't figure out what might be causing it.

2

There are 2 answers

0
John Sully On BEST ANSWER

The research I did late Friday and Saturday morning provided the answer to this one.

I had some code attached to the Sys.WebForms.PageRequestManager endRequest event which updated a text box which contained a temporary title for a new ration. The code looked like this:

    ///
    /// 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() referenced the options list of the animal weight 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';
    }

However if the list had not yet been populated the reference to options caused a fault which halted endRequest processing. Rather than having this code run on every async request I changed it to be a handler for the change event on the animal group ddl, like this:

    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);
    }

Then in animalWeightDdlOnLoad() I added a line to remove the handler once the request had run. This ensured that the change handler for the weight ddl would only run once the list had been populated. Problem solved. But just in case, I added a check on the length of the animal weight ddl's options list.

So even seemingly innocent javascript can mess up your async request handling in the browser.

1
zey On

Firstly , If you use telerik rad control , I suggest you to change your asp:button to telerik:RadButton .
Here is example

  <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;
    }

Note that , you should add AutoPostBack="true" into your radButton .
And this links , MSDN Reference1 and MSDN Reference2 will show details of using update Panel .