This is a migrated thread and some comments may be shown as answers.

DestroyOnClose not working

3 Answers 245 Views
Window
This is a migrated thread and some comments may be shown as answers.
Martin
Top achievements
Rank 1
Martin asked on 02 Feb 2012, 04:08 PM
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!!

3 Answers, 1 is accepted

Sort by
0
Marin Bratanov
Telerik team
answered on 03 Feb 2012, 05:29 PM
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
0
Martin
Top achievements
Rank 1
answered on 03 Feb 2012, 09:09 PM
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
0
Marin Bratanov
Telerik team
answered on 06 Feb 2012, 04:01 PM
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 >>
Tags
Window
Asked by
Martin
Top achievements
Rank 1
Answers by
Marin Bratanov
Telerik team
Martin
Top achievements
Rank 1
Share this question
or