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

Dynamic RadDock with User Control containing Ajaxified RadGrid

10 Answers 194 Views
Dock
This is a migrated thread and some comments may be shown as answers.
Martin Roussel
Top achievements
Rank 1
Martin Roussel asked on 08 Nov 2012, 03:21 PM
Hi,

My application is using different User Controls containing one RadGrid in each (some controls have hierarchy, some not). The Grids have ajaxified features such as "Add" command, "Refresh" command, export, row context menu etc. These User Controls work as expected either placed directly on a page, loaded dynamically in a native asp PlaceHolder or loaded dynamically loaded into a RadTabStrip. Im trying now to make them work into RadDocks. When trying to replicate the demos on your site (especially this one: My Portal), I can make it work but partially, since im running into different problems. The draggable docks containing user control are there but problems start when starting to use the grids inside.

#1 - if I use the Triggers/AsyncPostBackTrigger (like in the demo and below) to ajaxify the AddDock button, the grids for newly added docks seem to be unable to register their javascript code (getting errors like: ReferenceError: RowContextMenu is not defined). Grid's "OnItemCommand" is fired but code fails at "ScriptManager.RegisterStartupScript(...)" I also sometimes experience weird behaviors from the docks (cant close/drag/collapse them). If I refresh the page, docks loaded from save state are not experiencing such issue and seems to work as expected (except for issue #2 mentioned below)

<Triggers>
       <asp:AsyncPostBackTrigger ControlID="ButtonAddDock" EventName="Click"></asp:AsyncPostBackTrigger>
</Triggers>

I also tried to replace the triggers for AjaxSettings, and getting similar results:
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server" ClientEvents-OnRequestStart="mngRequestStarted">
                        <AjaxSettings>
                               <telerik:AjaxSetting AjaxControlID="ButtonAddDock">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>
                                <telerik:AjaxSetting AjaxControlID="ButtonAddDock2">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>
                                <telerik:AjaxSetting AjaxControlID="ButtonAddDock3">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>
                        </AjaxSettings>
</telerik:RadAjaxManager>

#2- If I comment out the trigger tags (or RadAjaxManager's AjaxSettings) , I now have postbacks on dock creation, but at least the issue #1 seem to go away. However, when I use a dock that contains a control that contains a hierarchy grid (2 levels), I always get (also experienced in issue #1 scenario) the following error when one or more rows are expanded and I want to do an ajax call from the grid (or another one), for instance grid's "Refresh". This time, the "OnItemCommand" event is not fired at all.

From FF:
Timestamp: 11/8/2012 11:12:10 AM
Error: Sys.WebForms.PageRequestManagerServerErrorException: Sys.WebForms.PageRequestManagerServerErrorException: Specified argument was out of the range of valid values.
Parameter name: ItemHierarchicalIndex
Source File: http://localhost:2917/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=RadScriptManager1_TSM&compress=1&_TSM_CombinedScripts_=%3b%3bAjaxControlToolkit%2c+Version%3d4.1.60501.0%2c+Culture%3dneutral%2c+PublicKeyToken%3d28f01b0e84b6d53e%3aen-US%3a5c09f731-4796-4c62-944b-da90522e2541%3aea597d4b%3ab25378d2%3bTelerik.Web.UI%2c+Version%3d2012.2.607.40%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a767fb6c3-728b-40e9-af4d-abc498bcae6e%3a16e4e7cd%3aed16cbdc%3af7645509%3a24ee1bba%3af46195d3%3a854aa0a7%3a874f8ea2%3a5a6d9d23%3a19620875%3a39040b5c%3af85f9819%3a58366029%3a2003d0b8%3ae330518b%3a1e771326%3ac8618e41%3ae4f8f289%3ac172ae1e%3a9cdfc6e7%3a490a9d4e%3abd8f85e4
Line: 9

Before I submit a sample or the rest of my code, Im asking if there is already a similar sample available for reference. I think must specify that my grid user controls use a RadAjaxManagerProxy.

TIA

10 Answers, 1 is accepted

Sort by
0
Martin Roussel
Top achievements
Rank 1
answered on 08 Nov 2012, 03:58 PM
duplicated post
0
Martin Roussel
Top achievements
Rank 1
answered on 08 Nov 2012, 04:07 PM
here is BTW the full code for the page containing the RadDockLayout:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Dashboard.aspx.cs" Inherits="PL.Dashboard" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <link href="~/Styles/Styles.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript" src="Scripts/myJQuery.js"></script>
    <title></title>
     
</head>
<body>
 
 
    <form id="form1" runat="server">
 
        <div class="ContentOuter">
               <div class="ContentInner">
 
                    <telerik:RadScriptManager runat="server" ID="RadScriptManager1" />
 
                    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server" ClientEvents-OnRequestStart="mngRequestStarted">
                        <AjaxSettings>
                               <%--<telerik:AjaxSetting AjaxControlID="ButtonAddDock">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>
                                <telerik:AjaxSetting AjaxControlID="ButtonAddDock2">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>
                                <telerik:AjaxSetting AjaxControlID="ButtonAddDock3">
                                    <UpdatedControls>
                                        <telerik:AjaxUpdatedControl ControlID="RadDockLayout1" />
                                    </UpdatedControls>
                                </telerik:AjaxSetting>--%>
                        </AjaxSettings>
                    </telerik:RadAjaxManager>
                     
                     
 
                    <asp:Button runat="server" ID="ButtonAddDock" Text="Add Dock (AJAX)" OnClick="ButtonAddDock_Click" ></asp:Button> <%-- OnClientClick="AddDock(); return false;"--%>
                    <asp:Button runat="server" ID="ButtonAddDock2" Text="Add Dock (AJAX)2" OnClick="ButtonAddDock_Click2" ></asp:Button>
                    <asp:Button runat="server" ID="ButtonAddDock3" Text="Add Dock (AJAX)3" OnClick="ButtonAddDock_Click3" ></asp:Button>
 
                    
                    
                    <asp:UpdatePanel style="position:absolute;height:100%;width:98%;" runat="server" ID="UpdatePanel2" ChildrenAsTriggers="false" UpdateMode="Conditional">
                        <ContentTemplate>
                            <br />
                            <telerik:RadDockLayout runat="server" ID="RadDockLayout1" OnSaveDockLayout="RadDockLayout1_SaveDockLayout" OnLoadDockLayout="RadDockLayout1_LoadDockLayout" >
                                <telerik:RadDockZone runat="server" ID="RadDockZone1" Width="99%" MinHeight="300" Orientation="vertical"
                                    Style="float: left; margin-right: 15px;">
                                </telerik:RadDockZone>
                                
                            </telerik:RadDockLayout>
                        </ContentTemplate>
                        <%--<Triggers>
                            <asp:AsyncPostBackTrigger ControlID="ButtonAddDock" EventName="Click"></asp:AsyncPostBackTrigger>--%>
                            <%--<asp:AsyncPostBackTrigger ControlID="ButtonAddDock2" EventName="Click"></asp:AsyncPostBackTrigger>
                            <asp:AsyncPostBackTrigger ControlID="ButtonAddDock3" EventName="Click"></asp:AsyncPostBackTrigger>--%>
                        <%--</Triggers>--%>
                    </asp:UpdatePanel>
                  
 
                    <div style="width: 0px; height: 0px; overflow: hidden; position: absolute; left: -10000px;">
                        <asp:UpdatePanel runat="server" ID="UpdatePanel1">
                        </asp:UpdatePanel>
                    </div>
 
               </div>
        </div>
    </form>
</body>
</html>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
 
namespace PL
{
    public partial class Dashboard : System.Web.UI.Page
    {
      
        private bool _dockStateCleared = false;
        private List<DockState> CurrentDockStates
        {
            get
            {
                //Store the info about the added docks in the session. For real life
                // applications we recommend using database or other storage medium
                // for persisting this information.
                List<DockState> _currentDockStates = (List<DockState>)Session["CurrentDockStatesMyPortal"];
                if (Object.Equals(_currentDockStates, null))
                {
                    _currentDockStates = new List<DockState>();
                    Session["CurrentDockStatesMyPortal"] = _currentDockStates;
                }
                return _currentDockStates;
            }
            set
            {
                Session["CurrentDockStatesMyPortal"] = value;
            }
        }
 
        protected void Page_Init(object sender, EventArgs e)
        {
            //Recreate the docks in order to ensure their proper operation
            for (int i = 0; i < CurrentDockStates.Count; i++)
            {
 
                RadDock dock = CreateRadDockFromState(CurrentDockStates[i]);
                //We will just add the RadDock control to the RadDockLayout.
                // You could use any other control for that purpose, just ensure
                // that it is inside the RadDockLayout control.
                // The RadDockLayout control will automatically move the RadDock
                // controls to their corresponding zone in the LoadDockLayout
                // event (see below).
                RadDockLayout1.Controls.Add(dock);
                //We want to save the dock state every time a dock is moved.
                CreateSaveStateTrigger(dock);
                //Load the selected widget
                LoadWidget(dock);
                if (CurrentDockStates[i].Closed == true)
                {
                    dock.Visible = false;
                }
            }
        }
 
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
 
        protected void RadDockLayout1_LoadDockLayout(object sender, DockLayoutEventArgs e)
        {
            //Populate the event args with the state information. The RadDockLayout control
            // will automatically move the docks according that information.
            foreach (DockState state in CurrentDockStates)
            {
                e.Positions[state.UniqueName] = state.DockZoneID;
                e.Indices[state.UniqueName] = state.Index;
            }
        }
 
        protected void RadDockLayout1_SaveDockLayout(object sender, DockLayoutEventArgs e)
        {
            if (!_dockStateCleared)
            {
                //Save the dock state in the session. This will enable us
                // to recreate the dock in the next Page_Init.
                CurrentDockStates = RadDockLayout1.GetRegisteredDocksState();
            }
            else
            {
                //the clear state button was clicked, so we refresh the page and start over.
                Response.Redirect(Request.RawUrl, false);
            }
        }
 
        private void CreateSaveStateTrigger(RadDock dock)
        {
            //Ensure that the RadDock control will initiate postback
            // when its position changes on the client or any of the commands is clicked.
            //Using the trigger we will "ajaxify" that postback.
            dock.AutoPostBack = true;
            dock.CommandsAutoPostBack = true;
 
            AsyncPostBackTrigger saveStateTrigger = new AsyncPostBackTrigger();
            saveStateTrigger.ControlID = dock.ID;
            saveStateTrigger.EventName = "DockPositionChanged";
            UpdatePanel1.Triggers.Add(saveStateTrigger);
 
            saveStateTrigger = new AsyncPostBackTrigger();
            saveStateTrigger.ControlID = dock.ID;
            saveStateTrigger.EventName = "Command";
            UpdatePanel1.Triggers.Add(saveStateTrigger);
        }
 
        protected void ButtonAddDock_Click(object sender, EventArgs e)
        {
            RadDock dock = CreateRadDock();
            //find the target zone and add the new dock there
            //RadDockZone dz = (RadDockZone)this.Master.FindControl("ContentPlaceHolder1").FindControl(DropDownZone.SelectedItem.Text);
 
            //adding the dock to the docklayout and then docking it to the zone to avoid ViewState issues on subsequent postback
            RadDockLayout1.Controls.Add(dock);
            dock.Dock(RadDockZone1);
 
            CreateSaveStateTrigger(dock);
 
            //Load the selected widget in the RadDock control
            dock.Tag = "ucSimpleGrid1.ascx";
            LoadWidget(dock);
        }
 
        protected void ButtonAddDock_Click2(object sender, EventArgs e)
        {
            RadDock dock = CreateRadDock();
            //find the target zone and add the new dock there
            //RadDockZone dz = (RadDockZone)this.Master.FindControl("ContentPlaceHolder1").FindControl(DropDownZone.SelectedItem.Text);
 
            //adding the dock to the docklayout and then docking it to the zone to avoid ViewState issues on subsequent postback
            RadDockLayout1.Controls.Add(dock);
            dock.Dock(RadDockZone1);
 
            CreateSaveStateTrigger(dock);
 
            //Load the selected widget in the RadDock control
            dock.Tag = "ucHierarchyGrid2.ascx";
            LoadWidget(dock);
        }
 
        protected void ButtonAddDock_Click3(object sender, EventArgs e)
        {
            RadDock dock = CreateRadDock();
            //find the target zone and add the new dock there
            //RadDockZone dz = (RadDockZone)this.Master.FindControl("ContentPlaceHolder1").FindControl(DropDownZone.SelectedItem.Text);
 
            //adding the dock to the docklayout and then docking it to the zone to avoid ViewState issues on subsequent postback
            RadDockLayout1.Controls.Add(dock);
            dock.Dock(RadDockZone1);
 
            CreateSaveStateTrigger(dock);
 
            //Load the selected widget in the RadDock control
            dock.Tag = "ucHierarchyGrid3.ascx";
            LoadWidget(dock);
        }
 
         
 
        private RadDock CreateRadDockFromState(DockState state)
        {
            RadDock dock = new RadDock();
            dock.DockMode = DockMode.Default;
            dock.Resizable = true;
            dock.ID = string.Format("RadDock{0}", state.UniqueName);
            dock.ApplyState(state);
            dock.Commands.Add(new DockCloseCommand());
            dock.Commands.Add(new DockExpandCollapseCommand());
 
            return dock;
        }
 
        private RadDock CreateRadDock()
        {
            RadDock dock = new RadDock();
            dock.DockMode = DockMode.Default;
            dock.Resizable = true;
            dock.UniqueName = Guid.NewGuid().ToString().Replace("-", "a");
            dock.ID = string.Format("RadDock{0}", dock.UniqueName);
            dock.Title = "Dock";
            dock.Text = string.Format("Added at {0}", DateTime.Now);
            dock.Width = Unit.Pixel(300);
 
            dock.Commands.Add(new DockCloseCommand());
            dock.Commands.Add(new DockExpandCollapseCommand());
 
            return dock;
        }
 
        private void LoadWidget(RadDock dock)
        {
            if (string.IsNullOrEmpty(dock.Tag) || dock.Closed)
            {
                return;
            }
            Control widget = LoadControl(dock.Tag);
 
            widget.EnableViewState = false;
            dock.ContentContainer.Controls.Add(widget);
        }
 
    }
}
0
Martin Roussel
Top achievements
Rank 1
answered on 08 Nov 2012, 04:09 PM
UPDATE: Ive found a topic (TOPIC) where someone was experiencing similar problems and the solution provided there seem to give hints to the solution for my issues.

Ive tried updating my code with the following:

.cs (in user control Page_Load)
string script = string.Format("var panel = $get('{0}'); if(panel)$telerik.evalScripts(panel);", Panel1.ClientID);
ScriptManager.RegisterStartupScript(this, this.GetType(), "scriptEval", script, true);

.ascx (user control)
<asp:Panel ID="Panel1" runat="server">
   <script type="text/javascript">
    
     //user control javascript code
 
    </script>
</asp:Panel>

.aspx (RadDockLayout page)
<Triggers>
                            <asp:AsyncPostBackTrigger ControlID="ButtonAddDock" EventName="Click"></asp:AsyncPostBackTrigger>
                            <asp:AsyncPostBackTrigger ControlID="ButtonAddDock2" EventName="Click"></asp:AsyncPostBackTrigger>
                            <asp:AsyncPostBackTrigger ControlID="ButtonAddDock3" EventName="Click"></asp:AsyncPostBackTrigger>
</Triggers>

It seems to help for Issue #1 since most grid actions now works without postback (like: Add new record) and im not getting undefined javascript function errors. However, the grid rebinding is not showing the RadAjaxLoadingPanel anymore (but the grid is refreshing the data though) and the export is not working (it just screws the column width and row height). Exporting works fine after a postback though. I also have problem to add new docks before a postback has occured.

Thanks again
0
Martin Roussel
Top achievements
Rank 1
answered on 08 Nov 2012, 04:10 PM
duplicated post
0
Slav
Telerik team
answered on 13 Nov 2012, 11:19 AM
Hello Martin,

I have prepared a sample page, which demonstrates how to setup the RadDocks that contain RadGrids. The export feature of the grid works only with regular postbacks as you can check here. I have handled the OnRequestStart event of the grid in order to ensure that a postback will be initiated when the export button is clicked.

Please use the attached sample as a reference for your future development.

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.
0
Martin Roussel
Top achievements
Rank 1
answered on 13 Nov 2012, 07:45 PM
Slav,

thanks to your sample, ive finally found out the culprit for issue #2. It was this line in the LoadWidget server-side function of the RadDockLayout page:

private void LoadWidget(RadDock dock)
        {
            if (string.IsNullOrEmpty(dock.Tag) || dock.Closed)
            {
                return;
            }
            Control widget = LoadControl(dock.Tag);
            widget.EnableViewState = false; <----------------------NEED TO REMOVE THIS LINE
            dock.ContentContainer.Controls.Add(widget);
        }

It came when I copied some code from the My Portal demo (DEMO). In order to help future cases, im wondering if this line really needed for the demo to work? Might be a good idea to remove it if not since it might confuse other people.

For issue #1, from the start, your sample has an unexpected behavior -> the grid's "Refresh" is not showing the RadLoadingPanel. Also, if you add a simple javascript function into the user control (in this case ucSimpleGrid1.ascx) like this:

<asp:Panel ID="Panel1" runat="server">
    <script type="text/javascript">
        function OnRowClick(sender, args) {
            alert("row clicked");
        }
    </script>
</asp:Panel>

and binded to the grid:
<ClientSettings ReorderColumnsOnClient="True" AllowDragToGroup="True" AllowColumnsReorder="True">
...
        <ClientEvents OnRowClick="OnRowClick"></ClientEvents>
</ClientSettings>

You'll receive the error: "ReferenceError: OnRowClick is not defined" on almost every dock action. I tried adding the following into the control load function, without success:
protected void Page_Load(object sender, EventArgs e)
    {
        string script = string.Format("var panel = $get('{0}'); if(panel)$telerik.evalScripts(panel);", Panel1.ClientID);
        ScriptManager.RegisterStartupScript(this, this.GetType(), "scriptEval", script, true);
    }


However, if you remove the AjaxSettings from RadAjaxManager1 (Default.aspx), then all these issues are gone (but you now we see the browser loading icon when adding/moving the docks).

Please let me know if you experience same thing on your side with these changes

TIA
0
Slav
Telerik team
answered on 16 Nov 2012, 03:03 PM
Hello Martin,

Indeed, it is a good idea to enable the view state in the loaded user controls as this will prevent potential problems with various controls in their content. This demo will be modified in a future update of the RadControls' demos.

The problem with the missing loading panel appears to be related to the asynchronous loading of the RadAjaxLoadingPanel's skin. To ensure it is loaded properly, please add a RadStyleSheetManager with the following setup on the main page:
<telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server">
    <StyleSheets>
        <telerik:StyleSheetReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Skins.Ajax.css" />
        <telerik:StyleSheetReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Skins.Black.Ajax.Black.css" />
    </StyleSheets>
</telerik:RadStyleSheetManager>

As for the OnRowClick event handler, you need to to wrap the client script in a RadScriptBlock to evaluate it and the issue will be fixed:
<telerik:RadScriptBlock runat="server" ID="RadCodeBlock1">
    <script type="text/javascript">
        function OnRowClick(sender, args)
        {
            alert("row clicked");
        }
    </script>
</telerik:RadScriptBlock>


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.
0
Martin Roussel
Top achievements
Rank 1
answered on 16 Nov 2012, 05:14 PM
Slav,

the RadStyleSheetManager seems to do the trick for the LoadingPanel issue. On the other hand, ive already tried wrapping my javascript into a RadCodeBlock and the problematic behavior ive described is still there. In fact, it only works if I do a page refresh that reload the docks. Can you re-submit a sample with your mentioned solutions so I can see what im doing wrong on my side.

Thanks

0
Slav
Telerik team
answered on 21 Nov 2012, 11:18 AM
Hello Martin,

You can find attached my sample page. Please use it as a reference for implementing the desired functionality in your project.

Greetings,
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.
0
Martin Roussel
Top achievements
Rank 1
answered on 21 Nov 2012, 05:15 PM
Slav,

The problem was I confused "RadScriptBlock" and "RadCodeBlock". Replacing my RadCodeBlocks for RadScriptBlocks fixed it.


Thanks again
Tags
Dock
Asked by
Martin Roussel
Top achievements
Rank 1
Answers by
Martin Roussel
Top achievements
Rank 1
Slav
Telerik team
Share this question
or