ModalPopupExtender gets stuck in Show when same TargetControlID is activated

130 Views Asked by At

I have a ModalPopupExtender tied to a RadListBox so that when an item is selected from the list box, I need a "Please Wait" message while the page behind loads the data into RadCharts. The Modal does Hide when the loading is completed. The problem I'm having is if the same list item is selected again, the Modal popup shows again, but never goes away. I've tried just about everything, but the click/selection of a list item in the RadListBox immediately shows the Modal and I can't seem to find a way to do item checking to see if its the same item, then to do nothing.

Here is my Panel and Modal code (ASPX)

<asp:Panel ID="pnlProgress" runat="server" Height="50px" Width="50px" >
     <div>
        <div class="popupbody">
            <table width="50%">
                <tr>
                    <td align="center">
                    <asp:Image ID="imgProgress" runat="server" ImageUrl="~/_images/ajax-loader.gif" />
                    <br />
                    <br />
                    <asp:Label ID="lblLoading" runat="server" Text='Please wait...'
                         Font-Bold="true"></asp:Label>
                    </td>
                </tr>
            </table>
        </div>
    </div>
</asp:Panel>

<ajaxToolKit:ModalPopupExtender ID="mpeProgress" runat="server" TargetControlID="lboxTestedMachines" PopupDragHandleControlID="pnlProgress" `enter code here`
X="1000" Y="500" PopupControlID="pnlProgress" BackgroundCssClass="modalBackground" RepositionMode="RepositionOnWindowResize" BehaviorID="lboxTestedMachines">
</ajaxToolKit:ModalPopupExtender>

And here is my ASPX.CS code

        protected void lboxTestedMachines_SelectedIndexChanged(object sender, EventArgs e)
    {
        int iResultID = Convert.ToInt32(lboxTestedMachines.SelectedValue);

        if (tbl_charts.Style.Value != "display:normal")
            tbl_charts.Style.Value = "display:normal";

        GetMachineName(iResultID);

        RdListView_Chart.DataSource = LoadCassetteForFoodChart(iResultID);

        GetApprovalRejectionStatus(iResultID);

    }
1

There are 1 best solutions below

1
On

The RadListBox has an internal logic on item click to determine if the item was already selected. If it was, it would not trigger the OnClientSelectedIndexChanging event, hence no postback on clicking a selected item.

The ModalPopupBehavior on the other hand reacts to any click event inside TargetControlID control's element. Here are some code snippets obtained using the browser's DevTools (search for Sys.Extended.UI.ModalPopupBehavior.prototype.initialize by following steps from Get IntelliSense for the client-side object)

initialize: function() {
    Sys.Extended.UI.ModalPopupBehavior.callBaseMethod(this, "initialize"),
        this._isIE6 = Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version < 7,
        this._popupDragHandleControlID && (this._dragHandleElement = $get(this._popupDragHandleControlID)),
        this._popupElement = $get(this._popupControlID),
        this._createDomElements(),
        this._showHandler = Function.createDelegate(this, this._onShow),
        $addHandler(this.get_element(), "click", this._showHandler),
        this._okControlID && (this._okHandler = Function.createDelegate(this, this._onOk),
            $addHandler($get(this._okControlID), "click", this._okHandler)),
        this._cancelControlID && (this._cancelHandler = Function.createDelegate(this, this._onCancel),
            $addHandler($get(this._cancelControlID), "click", this._cancelHandler)),
        this._scrollHandler = Function.createDelegate(this, this._onLayout),
        this._resizeHandler = Function.createDelegate(this, this._onLayout),
        this.registerPartialUpdateEvents(),
        this._resetAnimationsTarget(),
        this._onHiding.get_animation() && (this._hidingAnimationEndedHandler = Function.createDelegate(this, function () {
            this._isAnimationJustEnded = !0,
                this.hide()
        }),
            this._onHiding.get_animation().add_ended(this._hidingAnimationEndedHandler)),
        this._onShowing.get_animation() && (this._showingAnimationEndedHandler = Function.createDelegate(this, function () {
            this._isAnimationJustEnded = !0,
                this.show()
        }),
            this._onShowing.get_animation().add_ended(this._showingAnimationEndedHandler))
},
_onShow: function(e) {
    if (!this.get_element().disabled)
        return this.show(),
        e.preventDefault(),
        !1
},

Solution 1: Subscribe to the Showing event of the ModalPopupBehavior and allow it to show only when you set a flag from the OnClientSelectedIndexChanging event. The example below stores the flag in the RadListBox client-side object as an expando property:

<telerik:RadCodeBlock runat="server" ID="rdbScripts">
    <script type='text/javascript'> 
        function pageLoadHandler() {
            var modalPopupExtenderClientObject = $find("<%= mpeProgress.ClientID %>")
            modalPopupExtenderClientObject.add_showing(function (sender, args) {
                // "sender" argument represents the Modal popup control client-side object
                // sender.get_element() returns the DOM element of the RadListBox
                // sender.get_element().control return the client-side object of the RadListBox where we stored the expando property __allowModalPopupShow 
                if (sender.get_element().control.__allowModalPopupShow !== true) {
                    args.set_cancel(true);
                }
            })

        }

        function OnClientSelectedIndexChanging(sender, args) {
            // sender in this context is the RadListBox client-side object
            sender.__allowModalPopupShow = true;
        }

        Sys.Application.add_load(pageLoadHandler);
    </script>
</telerik:RadCodeBlock>

Solution 2: Use RadAjaxLoading panel and show it programmatically in OnClientSelectedIndexChanging: