DestroyOnClose not working

4 posts, 0 answers
  1. Martin
    Martin avatar
    39 posts
    Member since:
    Dec 2011

    Posted 02 Feb 2012 Link to this post

    I originally posted this as a reply to a year old post.

    I have a RadWindowManager with DestroyOnClose='true' but on every postback, even after closing the window theRadWindowManager's Windows collection still contains the window. I do not have VisibleOnPageLoad set. Instead, on every load, I run the following javascript.

    function openPromoteWindows(RadWindowManagerId) {
        var oManager = $find(RadWindowManagerId);
        var oWindows = oManager.GetWindows();
        for (i = 0; i < oWindows.length; i++) {
            var oWindow = oWindows[i];
            oWindow.show();
            oWindow.Minimize();
            oWindow.get_popupElement().style.zIndex = 10000 + i;
        }
    }

    This successfully opens all the windows minimized inside a taskbar. The problem is that since closed windows are still in the Windows Collection, they reappear.

    I did write some code called "OnClientClose that does successfully delete the window from the windows collection on the client side, but it doesn't persist. That code is below:

    function rwmPromote_Close(sender, eventargs) {
        var rwm = $find(window['rwmPromoteId']);
        var oWindows = rwm.GetWindows();
        var i;
        for (i = 0; i < oWindows.length; i++) {
            var oWindow = oWindows[i];
            if (oWindow == sender)
                break;
        }
        if (i < oWindows.length) {
            rwm._windows.splice(i, 1);
        }
    }

    This code was added in desperation to try and get the information persisted to the server side. I tried setting EnableViewState to false, but as expected that makes it forget about all Windows in the Windows collection except for ones added during that postback, which means it does forget about closed windows but also forgets about minimized windows.

    I am about to add a HiddenField which will contain the ClientIDs of all Windows and then I will use that server side to deduce which windows, if any, were closed. While I am hopeful this will work, I am sure it's not the way it is supposed to work.

    Added later! I have implemented the HiddenField solution as follows and it works successfully, but I don't think this is the proper way to achieve my goal.

    function rwmPromote_Close(sender, eventargs) {
        var rwm = $find(window['rwmPromoteId']);
        var hf = $get(window['hfWindowIdsId']);
        hf.value = '';
        var oWindows = rwm.GetWindows();
        var i;
        for (i = 0; i < oWindows.length; i++) {
            var oWindow = oWindows[i];
            if (oWindow == sender)
                break;
        }
        if (i < oWindows.length) {
            rwm._windows.splice(i, 1);
            oWindows = rwm.GetWindows();
            for (i = 0; i < oWindows.length; i++) {
                hf.value += oWindows[i].id + ',';
            }
        }
    }
     
    and in the code behind.

    // At the conclusion of every postback
      
    hfWindowIds.Value = "";
    foreach (RadWindow rw in rwmPromote.Windows)
    {
        hfWindowIds.Value += rw.ClientID + ',';
    }
     
    // And then on the ValueChanged event for the HiddenField
     
            protected void hfWindowIds_ValueChanged(object sender, EventArgs e)
            {
                char[] sep = {','};
                string[] WindowIds = ((HiddenField)sender).Value.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                List<RadWindow> rwList = new List<RadWindow>();
                foreach (RadWindow rw in rwmPromote.Windows)
                {
                    if (!WindowIds.Contains(rw.ClientID)) rwList.Add(rw); // No longer open client side
                }
                foreach (RadWindow rw in rwList)
                    rwmPromote.Windows.Remove(rw);  // Remove each closed window
            }
        }

    This is all working, but I would pre3fer to know the "correct" way to achieve my goal.

    Martin

    Suggestions welcomed!!
  2. Marin Bratanov
    Admin
    Marin Bratanov avatar
    5243 posts

    Posted 03 Feb 2012 Link to this post

    Hello Martin,

    Let me start with a little clarification on the DestroyOnClose property. What it does is remove the client-side markup and JavaScript object for the closed RadWindow. This is done to improve the page's performance especially in cases where multiple RadWindows are used. The server collection is persisted in the viewstate like with any other server control. It would be wrong if we deleted the items from the server collection, as this would mean that the end user can change or even break the developer's logic.

    Now, on saving the state of the RadWindows - the RadWindowManager exposes the legacy (meaning it is kept mostly for backwards compatibility) property PreserveClientState. When set to true it uses the unload event of the page to store the information about the RadWindows from the Windows collection of this RadWindowManager in a cookie on the user's machine. I believe it will be useful in your case, but please keep in mind the following: 1) cookies are not always reliable - they can be disabled on the browser, they can be deleted from the user, etc. In one session on the site (i.e. across several postbacks) there shouldn't be an issue, yet their integrity cannot be guaranteed for extended periods of time. Moreover, this cookie could be present the next time the user opens the site so he/she will see the state of the windows as they were left. This is sometimes the desired effect, other times not. 2) This is a legacy functionality, i.e. it is no longer developed and is designed to work in rather simpler scenarios - postbacks, across sessions mainly. It cannot be guaranteed to work in more complex scenarios (e.g. ajaxified pages, when the Windows collection is modified, etc.). What I can advise is that you try setting this property to true and carefully test your page. If it works as expected then you can keep using it, otherwise it would be best to stick with your current logic.


    Regards,
    Marin
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now
  3. Martin
    Martin avatar
    39 posts
    Member since:
    Dec 2011

    Posted 03 Feb 2012 Link to this post

    Hi Marin:

    Many thanks for the clarification. So if I understand you, I could set DestroyOnClose to true, and not process OnClientClose myself; instead I could trap ClientOnRequestStart and then, in THAT logic I could update the value of my HiddenField. This would achieve the same result, am I correct. And it would be preferable because the way I delete the window from the client side's window collection is not through a public interface and is prone to being broken in the future.
    Please confirm if my understanding is correct.

    Additionally, I suggest the following enhancement. Maybe during postback on the server you could fire an event, or series of events, like RadWindowDeleted or RadWindowModified and in the code behind I am given the choice of cancelling the deletion or modification. In order to be backwards compatible the default should be to cancel the update. This way, I could trap the deletion and allow it to proceed if the Window is one of those those where I wish to honor the user's wish.

    Martin
  4. Marin Bratanov
    Admin
    Marin Bratanov avatar
    5243 posts

    Posted 06 Feb 2012 Link to this post

    Hi Martin,

    The OnClientClose property removes the client-side object for this page load only - i.e. after a postback the entire collection from the server will be restored. The purpose of this property is to improve performance and memory consumption for the page, it does not change server collections either. Generally, the RadWindow is entirely a client-side object, the server-side collection is basically to ease declarations of properties. It does not render any markup from the server, which is one of its greatest strengths. If you wish to keep using your custom logic you still need the OnClientClose handler and DestroyOnClose will not aid you, since you perform postbacks and changes made on the client are not preserved across postbacks in any JavaScript object.

    As for server-side events - the RadWindow does not offer them and they are not a part of its design. This is a control that works on the client and therefore their events are client-side. If you wish to modify the Windows collection of a manager you can perform an AJAX request via JavaScript (e.g. with a RadAjaxManager) and pass the name of the RadWindow you need to work with in a hidden field, then in the code-behind you can iterate through the Widnows collection and when you find the one that matches your name (this is its server id) you can remove it from the collection. This is not functionality that is supported by the RadWindow as it is not designed to work on the server. Your current code should work and we do not plan to change the server collection functionality, so you can keep using it.

    The state preservation in a cookie, although legacy functionality, is not likely to be removed any time soon, I just advise that you test it carefully first, as such automation always comes at a price - handing complex scenarios is difficult and sometimes the behavior the developer envisions does not match exactly with the implemented functionality.


    Regards,
    Marin
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
Back to Top