Dock Disappearance in Fully Dynamic Layout

4 posts, 0 answers
  1. Allen
    Allen avatar
    10 posts
    Member since:
    Apr 2009

    Posted 07 Apr 2009 Link to this post

    Hello All,

    I am trying to create a "form layout designer" using RadTabStrip, RadPageView, RadDocks, as follows:

    1. A user can dynamically add tabs to the tab strip
    2. At the same time that a tab strip is added, I automatically add a page view "behind the scenes" so that there is a 1:1 correspondence with the tabs
    3. Inside each page view I automatically add a RadDockLayout
    4. A user can then dynamically add RadDockZones inside each layout (I am managing the placement and width via a combination of CSS and properties)
    5. Finally, users are free to select from a number of RadDocks, which then contain the form content, which they can then move freely between dock zones

    I have gotten items 1-4 working fine - the positioning of dock zones remains stable and predictable between post-backs. However, I am having trouble getting #5 to work reliably. Among the symptoms I see:

    • Only 1 dock appears after repeatedly adding docks to dock zones
    • After postback, even the 1 dock disappears

    Some details: as emphasized by the vast majority of documentation, it is best to create/re-create everything in Page_Init. Thus, I have:

            protected void Page_Init(object sender, EventArgs e)  
            {  
                // Re-create tabs (from persistence store) on the first page visit only  
                if (!Page.IsPostBack)  
                {  
                    for (int i = 0; i < CurrentTabCollection.Count; i++) { }  
                }  
     
                // Re-create page views  
                foreach (KeyValuePair<stringint> pageViewTuple in CurrentPageViewIdCollection) { CreateNewPageView(pageViewTuple.Key, pageViewTuple.Value); }  
     
                // Re-create dock layouts  
                foreach (KeyValuePair<stringint> dockLayoutTuple in CurrentDockLayoutIdCollection) { CreateNewDockLayout(dockLayoutTuple.Key, dockLayoutTuple.Value); }  
     
                // Re-create dock zones  
                foreach (KeyValuePair<stringstring> dockZoneTuple in CurrentDockZoneIdCollection) { CreateNewRadDockZone(dockZoneTuple.Key, dockZoneTuple.Value); }  
     
                // Re-create docks  
                for (int i = 0; i < CurrentDockStateCollection.Count; i++)  
                {  
                    RadDock dock = CreateRadDockFromState(CurrentDockStateCollection[i]);  
     
                    CreateSaveStateTrigger(dock);  
                }  
            } 

    Ignore the code about re-creating the tab collection - I'll use that later when I serialize/de-serialize to the database. Using reference code from Telerik, I have attached handlers for the SaveDockLayout and LoadDockLayout, like so:
            private void CreateNewDockLayout(string dockLayoutId, int parentTabIndex)  
            {  
                var newDockLayout = new RadDockLayout { ID = dockLayoutId };  
     
                newDockLayout.SaveDockLayout += FormSectionsRadDockLayout_SaveDockLayout; // Assign dock layout save handler  
                newDockLayout.LoadDockLayout += FormSectionsRadDockLayout_LoadDockLayout; // Assign dock layout load handler  
     
                FormSectionsRadMultiPage.PageViews[parentTabIndex].Controls.Add(newDockLayout);  
            } 

    And finally, inside the handlers:
            protected void FormSectionsRadDockLayout_SaveDockLayout(object sender, DockLayoutEventArgs e)  
            {  
                // Save the dock state in session  
                CurrentDockStateCollection = ((RadDockLayout)sender).GetRegisteredDocksState();  
            }  
     
            protected void FormSectionsRadDockLayout_LoadDockLayout(object sender, DockLayoutEventArgs e)  
            {  
                // Populate event args with state information; the RadDockLayout control will automatically move the docks according to this information  
                foreach (DockState state in CurrentDockStateCollection)  
                {  
                    e.Positions[state.UniqueName] = state.DockZoneID;  
                    e.Indices[state.UniqueName] = state.Index;  
                }  
            } 

    I also have all the related code to "create dock from state", "save state trigger", and so on. It seems that these are getting called correctly, but still I get the symptoms described above!

    Any ideas on what I'm missing here?

    Allen
  2. Allen
    Allen avatar
    10 posts
    Member since:
    Apr 2009

    Posted 08 Apr 2009 Link to this post

    Hi All,

    I have been able to resolve this and other related issues in full - posting some findings, perhaps this might be of help to someone in the same situation down the line.

    First, it wasn't that the approach was wrong, but more that it was incomplete. (Whether the approach is optimal or scalable is another matter, but I suppose I'll be finding that out in the next few days...)

    1. Docks created (and their states added to the list of dock states) seemed to disappear because the list was being overwritten (i.e. emptied) everytime a new "container" was created, whether a dock layout, or a page view. Thus, to fully capture status for docks in a number of containers, the list needs to look more like this:

            private Dictionary<int, List<DockState>> CurrentDockStateCollection  
            {  
                get 
                {  
                    var _currentDockStateCollection = (Dictionary<int, List<DockState>>)Session["CurrentDockStateCollection"];  
     
                    if (Equals(_currentDockStateCollection, null))  
                    {  
                        _currentDockStateCollection = new Dictionary<int, List<DockState>>();  
                        Session["CurrentDockStateCollection"] = _currentDockStateCollection;  
                    }  
     
                    return _currentDockStateCollection;  
                }  
            } 

    Thus, this is a "list of lists" (as I said, I don't know if this is optimal yet!). The int parameter is used to indicate which list of dock states is being operated on at any given time.

    2. Therefore, in Page_Init, the method to re-create all docks now looks like this:

               // Re-create RadDocks  
                for (int i = 0; i < CurrentTabCount; i++) // Process each tab in turn  
                {  
                    for (int j = 0; j < CurrentDockStateCollection[i].Count; j++)   
                    {  
                        RadDock dock = CreateRadDockFromState(CurrentDockStateCollection[i][j]); // Process each dock state  
     
                        // Add the dock back to the proper dock layout; the dock layout will be responsible for moving the dock to the proper zone  
                        FormSectionsRadMultiPage.PageViews[i].Controls[0].Controls.Add(dock);  
     
                        CreateSaveStateTrigger(dock);  
                    }     
                } 

    So, these two allow for consistent and reliable re-creation of docks, based on their state as captured in the appropriate list of dock state lists.

    Allen
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Martin Roussel
    Martin Roussel avatar
    246 posts
    Member since:
    Jan 2010

    Posted 21 Feb 2013 Link to this post

    Allen,

    I know this is an old post but your case is very similar to mine. Im trying to build a portal layout designer similar to your in the sense that users can:

    1-dynamically add/remove/rename tabs to the tab strip (Dashboard.aspx)
    2-At the same time that a tab is added, I automatically add a page view "behind the scenes" so that there is a 1:1 correspondence with the tabs
    3-Inside each page view I automatically add a user control (ucDashboard.ascx) containing a RadDockLayout and RadDockZone in the following way:
    <asp:Panel ID="Panel1" runat="server" class="DockContainerPanel">
                   <telerik:RadDockLayout runat="server" ID="RadDockLayout1" OnSaveDockLayout="RadDockLayout1_SaveDockLayout"
                       OnLoadDockLayout="RadDockLayout1_LoadDockLayout">
                     
                               <telerik:RadDockZone runat="server" ID="RadDockZone1" CssClass="DockZone" Orientation="vertical">
                               </telerik:RadDockZone>
                             
                   </telerik:RadDockLayout>
               </asp:Panel>
    so that there is a 1:1 correspondence with the pageview (and user cannot alter this).
    4-Finally, users are free to select from a number of RadDocks, (which contain each a content user control), which they can then move freely within the pageview unique dock zone.

    Everything seemed to work but recently noted that I have a dock position persistence problem (moved docks position are not persisted after state save/reload from database). After contacting the admins, ive been told "it will not be possible to load the user control with the RadDockLayout and its content dynamically. The dock layout control depends on events  that are raised early on the page lifecycle (Init event). In your case the dock layout is loaded on PageViewCreated of the RadMultiPage, which is fired too late for the dock state to be persisted properly." In your case, it seems you succeeded. Can you (or someone reading this) please help?

    here's how im loading the docks:
    Dictionary<string, string> dockParents = new Dictionary<string, string>();
     Dictionary<string, int> dockIndices = new Dictionary<string, int>();
     
     protected void Page_Init(object sender, EventArgs e)
     {
     
     
         GetDockStates();
     
        
         for (int i = 0; i < CurrentDockStates.Count; i++)
         {
     
             RadDock dock = CreateRadDockFromState(CurrentDockStates[i]);
             
             RadDockLayout1.Controls.Add(dock);
     
             dockParents.Add(CurrentDockStates[i].UniqueName, CurrentDockStates[i].DockZoneID);
             dockIndices.Add(CurrentDockStates[i].UniqueName, CurrentDockStates[i].Index);
     
             
             LoadWidget(dock, CurrentDockStates[i].Text, CurrentDockStates[i].Title);
             if (CurrentDockStates[i].Closed == true)
             {
                 dock.Visible = false;
             }
         }
     
        
     }
     
     protected void Page_Load(object sender, EventArgs e)
     {
         RadDockLayout1.SetRegisteredDockParents(dockParents, dockIndices);
     }

    If you need to see more code, please let me know.

    TIA

    Martin

  5. Slav
    Admin
    Slav avatar
    1355 posts

    Posted 26 Feb 2013 Link to this post

    Hello Martin,

    I have already suggested a solution in the support ticket on the matter. Let us continue our discussion there so the information on the case can tracked easier. When the issue is fixed you can post the solution this thread so that the community can benefit from it.

    Kind regards,
    Slav
    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.
Back to Top