Saving more than just dynamically created docks to Session

4 posts, 1 answers
  1. Sean
    Sean avatar
    200 posts
    Member since:
    Nov 2010

    Posted 20 Jan 2011 Link to this post

    Hi all,

    I was hoping to have a discussion about what all needs to occur when attempting to save and load dynamically created objects.

    I've looked through the following example pretty thoroughly and I feel like it is a good starting example, but leaves some complex concepts still untouched: http://demos.telerik.com/aspnet-ajax/dock/examples/myportal/defaultcs.aspx

    So, my first concern is usage of only a single RadDockLayout in this example. It is my understanding that scenarios will arrive where multiple RadDockLayouts will be necessary and that each RadDockLayout needs to be able to persist the state of controls inside of it. Does Telerik possess example code to handle this scenario? Could some be mocked up?

    For instance, in my scenario I have the following situation:
    • The web page loads and the user is presented with only one, blank RadPane.
    • The user has the ability to divide this RadPane up into subsections which will eventually hold RadDocks through the following strategy: 
    • 1) User indicates they would like to add a horizontal RadSplitBar to the screen.
    • 2) Dynamic creation of the following controls ensues:
    • a) RadSplitter will be our base foundation. Its orientation is horizontal.
    • b) RadPane will be contained in the RadSplitter.
    • c) RadDockLayout will be contained in the RadPane.
    • d) RadDockZone will be contained in the RadDockLayout.
    • e) RadSplitBar will be contained in RadSplitter.
    • f) Repeat steps b-d to replicate the 'other half' of RadSplitter's content.
    • 3) This RadSplitter is now added to the blank RadPane. 
    • The user now has control over two dynamically created, resizable RadDockZones.
    At this point it should be clear that the amount of objects requiring persistent state is going to be much larger than that of the simple example provided above. In addition, my scenario allows the user to continue adding more bars to their initial RadPane -- subdividing the initially blank square into many RadDockZones of various size. After investigating this issue further, I was able to find some sample code provided by a Telerik employee that showed a way of saving DockZone's to a database. In this example, they capture a specific RadDockLayout's RegisteredZones and write the list of names to a database. Then, they recreate each zone using only the name given in the database. This solution does not seem easily extensible, however. How would one handle an arbitrarily large amount of nested controls?
    Attempting to recreate the object structure I described above sounds near impossible. The user may have decided that they really like horizontal dividers. As such, they have nested the above object structure in itself multiple times. Each time, the code must strip away the RadDockZone and RadDockLayout and re-add the entire structure to the RadPane in order to 'split' it into two again. Then, when loading the hierarchy on page init, I cannot just load all RadDockZones. I must load the first splitter on the static pane, then the panes it holds, then splitters inside those panes (recursively going through any splitters added to the pane) before being able to go back through and add RadDockLayouts and RadDockZones to panes which do not have splitters on them.
    Whew! With all that being said, I feel like this goal is an achievable one. Unfortunately, I do not see a way of dumbing down this recursive-nesting in a way that would yield the same results that I desire.
    If I can provide any additional information, let me know. If a sample project with code would be helpful I can supply, but I will be the first to admit that my project is still in its infancy.
    Thank you for your time!
    EDIT: If it seems that creating a complicated mock-up would not be feasible at this point in time, would it be possible to receive a mock-up of a static RadPane saving/loading the state of another control?









  2. Answer
    Pero
    Admin
    Pero avatar
    1156 posts

    Posted 26 Jan 2011 Link to this post

    Hello Sean,

    Based on your description I think that your project should consist of two parts: Layout and Content. The Layout is represented by the RadSplitter and all the nested Panes, SplitBars and RadDockZones. The Content is represented by the RadDocks. The state of the Layout controls is serialized and saved independently from the one of the docks. Let me explain my idea of how the state of both parts will be saved:

    1. Content, i.e. RadDocks
    This is pretty much clear. The state should be saved using the approach shown in the MyPortal demo. We serialize the state of all docks registered with the DockLayout control, and then save it into the DB. One instance of RadDockLayout will be enough to manage the state of all the docks on the page. This Docking layout should be static (i.e. declared in the ASPX markup), and should contain the base Splitter and Pane. The RadDock controls, are created and added to the RadDockLayout - you need to provide the ClientID of the RadDockZone to which they belong, and the DockLayout will reposition the docks at their positions.

    2. Layout, i.e. Splitters, Panes, SplitBars and DockZones
    For each control should be created a corresponding ControlState object/class (for example Splitter - SplitterState, Pane - PaneState and etc.) that will save the state of the control needed to recreate it on postbacks. Every class should store all properties needed to recreate the respective object/control, and information about its child controls. The controls should have the same IDs across postbacks, so the IDs should be saved.
    Regarding the child controls:
    A RadPane can contain either a RadDockZone, or a RadSplitter. Therefore the PaneState object should have one property to save the ZoneState, and other the SplitterState. The Splitter control can contain either RadPanes or RadSplittBars, thus we need two Lists that will contain the states of all the Panes in the splitter. Every object of the PaneStates List will again store information about the controls it has. Here is a sample code, of how the "State" classes will look like:

    using System;
    using System.Collections.Generic;
    using Telerik.Web.UI;
    using System.Web.UI;
     
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            System.Web.Script.Serialization.JavaScriptSerializer serialzer = new System.Web.Script.Serialization.JavaScriptSerializer();
            PaneState paneState = serialzer.Deserialize<PaneState>("Serialzied State loaded from the DB!");
     
            //Create the Panes and Zones
     
            //Create Docks, and add them to the RadDockLayout
        }
     
        protected void SaveDockLayout(object sender, EventArgs e)
        {
            System.Web.Script.Serialization.JavaScriptSerializer serialzer = new System.Web.Script.Serialization.JavaScriptSerializer();
            var state = serialzer.Serialize(SerializePane(RadPane1));
            //Save the State into DB
        }
     
        /// <summary>
        /// Serializes a RadPane object and returns a PaneState.
        /// </summary>
        /// <param name="pane">The RadPane to serialize.</param>
        /// <returns></returns>
        private PaneState SerializePane(RadPane pane)
        {
            if (pane.Controls.Count < 1)
            {
                return null;
            }
     
            PaneState paneState = new PaneState();
            paneState.ID = pane.ID;
     
            foreach (Control item in pane.Controls)
            {
     
                if (item is RadDockZone)
                {
                    paneState.Zone = new ZoneState(item.ID);
                }
     
                if (item is RadSplitter)
                {
                    paneState.Splitter = new SplitterState(item.ID);
                    this.SerializeSplitter((RadSplitter)item, paneState.Splitter);
                    //Serialize splitter
                }
            }
     
            return paneState;
        }
     
        private void SerializeSplitter(RadSplitter splitter, SplitterState splitterState)
        {
            foreach (SplitterItem item in splitter.Items)
            {
                if (item is RadPane)
                {
                    splitterState.Panes.Add(SerializePane((RadPane)item));
                }
                else
                {
                    splitterState.SplitBars.Add(new SplitBarState(item.ID));
                }
            }
        }
     
        [Serializable]
        public class PaneState
        {
            public string ID
            {
                get;
                set;
            }
     
            public SplitterState Splitter
            {
                get;
                set;
            }
     
            public ZoneState Zone
            {
                get;
                set;
            }
        }
     
        [Serializable]
        public class SplitterState
        {
            public SplitterState(string id)
            {
                this.ID = id;
            }
     
            public string ID
            {
                get;
                set;
            }
     
            public List<PaneState> Panes;
            public List<SplitBarState> SplitBars;
        }
     
        [Serializable]
        public class SplitBarState
        {
            public SplitBarState(string id)
            {
                this.ID = id;
            }
     
            public string ID
            {
                get;
                set;
            }
        }
     
        [Serializable]
        public class ZoneState
        {
            public ZoneState(string id)
            {
                this.ID = id;
            }
            public string ID
            {
                get;
                set;
            }
        }
    }


    I hope this will give you an idea of how to start up your project. If you have other questions, or need help, do not hesitate to write. We will be glad to help.

    Greetings,
    Pero
    the Telerik team
    Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Sean
    Sean avatar
    200 posts
    Member since:
    Nov 2010

    Posted 27 Jan 2011 Link to this post

    This might be a silly question. I've got my program basically up and working, but I had used multiple DockLayouts. I am now re-working it to use only one DockLayout.

    My question is: Should a RadDockLayout's EnableViewState property be set to false when it's direct child is static, but it's grandchildren are dynamic? My current belief is "Yes, it should be set to false because regardless of its direct children the RadDockLayout is responsible for monitoring the position of dynamic controls."

    Just wanted to be sure. Thanks!
  5. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 28 Jan 2011 Link to this post

    Hi Sean,

    Yes it should be set to false, because all of its child controls are created dynamically, and their state is saved in the DB. If you still want some of the RadDockLayout's child controls to have ViewState you can set the StoreLayoutInViewState property to false and leave its ViewState enabled, and the dock state will not be saved in the ViewState.

    Best wishes,
    Pero
    the Telerik team
    Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
Back to Top