Problem Overview:
We are utilizing the RadDock controls to provide some dashboard/portal like functionality in our web site. Users are allowed to add RadDocks to the page dynamically. We have closely followed the example given at this website: http://demos.telerik.com/aspnet-ajax/dock/examples/dynamicdocks/defaultcs.aspx Essentially, the issue seems to appear when we are utizing AJAX to automatically post back for all dockposition changes. I have seen several types of these questions raised via google/telrik searches, but none specifically identical to my situation. So, I have created a sample project which is a whittled down, simplified version of our real application which demonstrates the issue.
The most prominent javascript error seems to be:
Symptoms/Cause
When users quickly move RadDocks around on the page the position of the RadDocks seem to get lost and they free float on the page causing javascript errors. A sure fire way to cause this error seems to be rapidly double clicking on the header bar of a RadDock. This will eventually result in a JavaScript error in which subsequent actions cause page to have several javascript errors rending the page useless.
Please NOTE: Double clicking was not the only method used to create the random javascript errors, however it seems to be the best way to easily reproduce the issue. I think all the javascript errors we have seen stem from the same root issue, whatever that may be.
We have tried several variations of using UpdatePanel and the RadAjaxPanel with Loading Panel. Any help that anyone can give would be appreciated.
Sample ASPX Page
Code Behind
We are utilizing the RadDock controls to provide some dashboard/portal like functionality in our web site. Users are allowed to add RadDocks to the page dynamically. We have closely followed the example given at this website: http://demos.telerik.com/aspnet-ajax/dock/examples/dynamicdocks/defaultcs.aspx Essentially, the issue seems to appear when we are utizing AJAX to automatically post back for all dockposition changes. I have seen several types of these questions raised via google/telrik searches, but none specifically identical to my situation. So, I have created a sample project which is a whittled down, simplified version of our real application which demonstrates the issue.
The most prominent javascript error seems to be:
Webpage error details | |
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; MDDR; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; InfoPath.2; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) | |
Timestamp: Wed, 16 Sep 2009 21:39:37 UTC | |
Message: 'undefined' is null or not an object | |
Line: 5033 | |
Char: 2 | |
Code: 0 | |
URI: http://as-qa-vm/AIMSNET/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl00_scriptManager_HiddenField&compress=1&_TSM_CombinedScripts_=%3b%3bTelerik.Web.UI%2c+Version%3d2009.2.826.35%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3ad2d891f5-3533-469c-b9a2-ac7d16eb23ff%3a874f8ea2%3a24ee1bba%3a19620875%3a33108d14%3abd8f85e4%3ae330518b%3a1e771326%3ac8618e41%3a854aa0a7%3a5a6d9d23 | |
Symptoms/Cause
When users quickly move RadDocks around on the page the position of the RadDocks seem to get lost and they free float on the page causing javascript errors. A sure fire way to cause this error seems to be rapidly double clicking on the header bar of a RadDock. This will eventually result in a JavaScript error in which subsequent actions cause page to have several javascript errors rending the page useless.
Please NOTE: Double clicking was not the only method used to create the random javascript errors, however it seems to be the best way to easily reproduce the issue. I think all the javascript errors we have seen stem from the same root issue, whatever that may be.
We have tried several variations of using UpdatePanel and the RadAjaxPanel with Loading Panel. Any help that anyone can give would be appreciated.
Sample ASPX Page
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RadAjaxPanelDoesNotWork.aspx.cs" Inherits="WebUI.RadAjaxPanelDoesNotWork" %> | |
<%@ Register assembly="Telerik.Web.UI" namespace="Telerik.Web.UI" tagprefix="telerik" %> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" > | |
<head runat="server"> | |
<title></title> | |
</head> | |
<body> | |
<form id="form1" runat="server"> | |
<telerik:RadScriptManager ID="RadScriptManager1" runat="server"> | |
</telerik:RadScriptManager> | |
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"> | |
<AjaxSettings> | |
<telerik:AjaxSetting AjaxControlID="Column1"> | |
<UpdatedControls> | |
<telerik:AjaxUpdatedControl ControlID="Column1" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column2" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column3" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
</UpdatedControls> | |
</telerik:AjaxSetting> | |
<telerik:AjaxSetting AjaxControlID="Column2"> | |
<UpdatedControls> | |
<telerik:AjaxUpdatedControl ControlID="Column1" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column2" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column3" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
</UpdatedControls> | |
</telerik:AjaxSetting> | |
<telerik:AjaxSetting AjaxControlID="Column3"> | |
<UpdatedControls> | |
<telerik:AjaxUpdatedControl ControlID="Column1" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column2" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
<telerik:AjaxUpdatedControl ControlID="Column3" | |
LoadingPanelID="RadAjaxLoadingPanel1" /> | |
</UpdatedControls> | |
</telerik:AjaxSetting> | |
</AjaxSettings> | |
</telerik:RadAjaxManager> | |
<telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" | |
Skin="Default" MinDisplayTime="500"> | |
</telerik:RadAjaxLoadingPanel> | |
<asp:Button ID="btnAdd" OnClick="btnAdd_Click" runat="server" Text="Add Dock"/> | |
<telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server"> | |
<telerik:RadDockLayout runat="server" ID="radDockLayout" OnSaveDockLayout="radDockLayout_SaveDockLayout" OnLoadDockLayout="radDockLayout_LoadDockLayout"> | |
<table style="width:99%;"> | |
<tr> | |
<td style="width: 30%;" valign="top" runat="server" Id="tblColumn1"> | |
<telerik:RadDockZone runat="server" ID="Column1" Orientation="vertical" Style="border: 0px; width: 100%; min-height: 400px; min-width:100px"> | |
</telerik:RadDockZone> | |
</td> | |
<td style="width: 30%;" valign="top" runat="server" Id="tblColumn2"> | |
<telerik:RadDockZone runat="server" ID="Column2" Orientation="vertical" Style="border: 0px; width: 100%; min-height: 400px; min-width:100px"> | |
</telerik:RadDockZone> | |
</td> | |
<td style="width: 30%;" valign="top" runat="server" Id="tblColumn3"> | |
<telerik:RadDockZone runat="server" ID="Column3" Orientation="vertical" Style="border: 0px; width: 100%; min-height: 400px; min-width:100px;"> | |
</telerik:RadDockZone> | |
</td> | |
</tr> | |
</table> | |
</telerik:RadDockLayout> | |
</telerik:RadAjaxPanel> | |
</form> | |
</body> | |
</html> | |
Code Behind
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Web.UI; | |
using System.Web.UI.WebControls; | |
using Telerik.Web.UI; | |
namespace WebUI | |
{ | |
public partial class RadAjaxPanelDoesNotWork : System.Web.UI.Page | |
{ | |
private IList<DockState> dockStates = new List<DockState>(); | |
private bool shouldSaveDocks = true; | |
#region page events | |
protected void Page_Init(object sender, EventArgs e) | |
{ | |
LoadDocks(); | |
} | |
protected void Page_Load(object sender, EventArgs e) | |
{ | |
if (!Page.IsPostBack) | |
{ | |
shouldSaveDocks = false; | |
} | |
} | |
protected void radDockLayout_LoadDockLayout(object sender, DockLayoutEventArgs e) | |
{ | |
//Populate the event args with the state information. The RadDockLayout control | |
//will automatically move the docks according that information. | |
var savedDockStates = GetDockStates(); | |
foreach (DockState dockState in savedDockStates) | |
{ | |
e.Positions[dockState.UniqueName] = dockState.DockZoneID; | |
e.Indices[dockState.UniqueName] = dockState.Index; | |
} | |
} | |
protected void radDockLayout_SaveDockLayout(object sender, DockLayoutEventArgs e) | |
{ | |
//Save the dock state in the db. This will enable us | |
// to recreate the dock in the next Page_Init. | |
if (shouldSaveDocks) | |
{ | |
List<DockState> dockStatesToSave = ((RadDockLayout)sender).GetRegisteredDocksState(); | |
SaveDockStates(dockStatesToSave); | |
} | |
} | |
protected void btnAdd_Click(object sender, EventArgs e) | |
{ | |
RadDock dock = CreateRadDock(); | |
Column1.Controls.Add(dock); | |
CreateSaveStateTrigger(dock); | |
dock.Title = "Sample User Control"; | |
LoadWidget(dock); | |
} | |
#endregion | |
#region Helper Methods | |
private void LoadDocks() | |
{ | |
dockStates = GetDockStates(); | |
//Recreate the docks in order to ensure their proper operation | |
foreach (DockState dockState in dockStates) | |
{ | |
if (dockState.Closed == false) | |
{ | |
RadDock dock = CreateRadDockFromState(dockState); | |
//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). | |
radDockLayout.Controls.Add(dock); | |
//We want to save the dock state every time a dock is moved. | |
CreateSaveStateTrigger(dock); | |
LoadWidget(dock); | |
} | |
} | |
} | |
private IList<DockState> GetDockStates() | |
{ | |
List<DockState> _currentDockStates = (List<DockState>)Session["DockStates"]; | |
if (Object.Equals(_currentDockStates, null)) | |
{ | |
_currentDockStates = new List<DockState>(); | |
Session["DockStates"] = _currentDockStates; | |
} | |
return _currentDockStates; | |
} | |
private void SaveDockStates(IEnumerable<DockState> dockStatesToSave) | |
{ | |
Session["DockStates"] = dockStatesToSave; | |
} | |
private static RadDock CreateRadDockFromState(DockState state) | |
{ | |
var dock = new RadDock { DockModeDockMode = DockMode.Docked, EnableAnimation = true, Skin = "Default", ID = string.Format("RadDock{0}", state.UniqueName) }; | |
dock.ApplyState(state); | |
//dock.EnableAnimation = false; | |
dock.Commands.Add(new DockCloseCommand()); | |
dock.Commands.Add(new DockExpandCollapseCommand()); | |
return dock; | |
} | |
private static RadDock CreateRadDock() | |
{ | |
var dock = new RadDock { DockModeDockMode = DockMode.Docked, EnableAnimation = true, Skin = "Default", UniqueName = Guid.NewGuid().ToString() }; | |
dock.ID = string.Format("RadDock{0}", dock.UniqueName); | |
//dock.EnableAnimation = false; | |
dock.Commands.Add(new DockCloseCommand()); | |
dock.Commands.Add(new DockExpandCollapseCommand()); | |
return dock; | |
} | |
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; | |
} | |
private void LoadWidget(RadDock dock) | |
{ | |
Control widget = LoadControl("~/UserControls/SampleUserControl.ascx"); | |
dock.ContentContainer.Controls.Add(widget); | |
} | |
#endregion | |
} | |
} | |