Right, well I've spent most of the day trying to figure this out using XRender and I'm getting to the limits of my patience with it...
This isn't really ASYNC chart loading. Each of the controls loads one after the other as I suspect the direct methods are handled synchronously, if 1 chart were to take 30 seconds to load, then the others have to wait for it to finish. I see this as a big disadvantage over IFrames.
Secondly, I just can't make it work as expected, I have a prototype (see below), and whenever you click reload in the left panel using the 'Reload' button and specifying which container you want to reload, e.g. 1 (top left quadrant) the container will reload but the loading mask will not work the SECOND time you click it, and clicking on the 'Test Direct Event' button produces all sorts of strange behaviour even though I'm re-creating the controls on every load and using ViewState to only create them after the initial control load. I still get odd 'Control with ID not found' errors....
DashboardXREnderPrototype.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DashboardXRenderPrototype.aspx.cs" Inherits="DevTesting.DashboardXRenderPrototype" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ext:ResourceManager ID="extResourceManager" runat="server" DirectMethodNamespace="CompanyX" />
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
var loadContainer = function (panel) {
panel.body.mask('Loading...', 'x-mask-loading');
CompanyX.LoadContainer(panel.id, panel.containerID, panel.loadTimeSecs, { viewStateMode: 'enabled' });
};
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<ext:Viewport ID="ViewPortMain" runat="server" Layout="border">
<Items>
<ext:Panel ID="headerPanel" runat="server" Region="North" Title="Header" Height="76">
<Content>
<ext:Button runat="server" ID="btnReloadAllCharts" Text="Reload All Charts">
<DirectEvents>
<Click OnEvent="ReloadAllCharts" />
</DirectEvents>
</ext:Button>
</Content>
</ext:Panel>
<ext:Panel ID="mainPanel" runat="server" Border="false" Region="Center" BodyStyle="background-color : #e4edfe;">
<Content>
<ext:BorderLayout runat="server">
<West MinWidth="175" MaxWidth="400" Split="true" Collapsible="true">
<ext:Panel Width="175" runat="server" Layout="FitLayout">
<Items>
<ext:Panel ID="Container0" runat="server" Title="XRenderPanel">
<CustomConfig>
<ext:ConfigItem Name="containerID" Value="0" Mode="Raw" />
<ext:ConfigItem Name="loadTimeSecs" Value="0" Mode="Raw" />
</CustomConfig>
<Tools>
<ext:Tool Type="Refresh" Handler="loadContainer(panel);" />
</Tools>
<Listeners>
<AfterRender Handler="loadContainer(this);" Delay="1"/>
</Listeners>
</ext:Panel>
</Items>
</ext:Panel>
</West>
<Center>
<ext:Container runat="server" Region="Center" Layout="VBoxLayout">
<LayoutConfig>
<ext:VBoxLayoutConfig Align="Stretch" />
</LayoutConfig>
<Items>
<ext:Container runat="server" Layout="HBoxLayout" Flex="1">
<LayoutConfig>
<ext:HBoxLayoutConfig Align="Stretch" />
</LayoutConfig>
<Items>
<ext:Panel ID="Container1" runat="server" Flex="1" Title="XRenderPanel">
<CustomConfig>
<ext:ConfigItem Name="containerID" Value="1" Mode="Raw" />
<ext:ConfigItem Name="loadTimeSecs" Value="0" Mode="Raw" />
</CustomConfig>
<Tools>
<ext:Tool Type="Refresh" Handler="loadContainer(panel);" />
</Tools>
<Listeners>
<AfterRender Handler="loadContainer(this);" Delay="1" />
</Listeners>
</ext:Panel>
<ext:Panel ID="Container2" runat="server" Flex="1" Title="XRenderPanel">
<CustomConfig>
<ext:ConfigItem Name="containerID" Value="2" Mode="Raw" />
<ext:ConfigItem Name="loadTimeSecs" Value="0" Mode="Raw" />
</CustomConfig>
<Tools>
<ext:Tool Type="Refresh" Handler="loadContainer(panel);" />
</Tools>
<Listeners>
<AfterRender Handler="loadContainer(this);" Delay="1" />
</Listeners>
</ext:Panel>
</Items>
</ext:Container>
<ext:Container runat="server" Layout="HBoxLayout" Flex="1">
<LayoutConfig>
<ext:HBoxLayoutConfig Align="Stretch" />
</LayoutConfig>
<Items>
<ext:Panel ID="Container3" runat="server" Flex="1" Title="XRenderPanel">
<CustomConfig>
<ext:ConfigItem Name="containerID" Value="3" Mode="Raw" />
<ext:ConfigItem Name="loadTimeSecs" Value="5" Mode="Raw" />
</CustomConfig>
<Tools>
<ext:Tool Type="Refresh" Handler="loadContainer(panel);" />
</Tools>
<Listeners>
<AfterRender Handler="loadContainer(this);" Delay="1" />
</Listeners>
</ext:Panel>
<ext:Panel ID="Container4" runat="server" Flex="1" Title="XRenderPanel">
<CustomConfig>
<ext:ConfigItem Name="containerID" Value="4" Mode="Raw" />
<ext:ConfigItem Name="loadTimeSecs" Value="5" Mode="Raw" />
</CustomConfig>
<Tools>
<ext:Tool Type="Refresh" Handler="loadContainer(panel);" />
</Tools>
<Listeners>
<AfterRender Handler="loadContainer(this);" Delay="1" />
</Listeners>
</ext:Panel>
</Items>
</ext:Container>
</Items>
</ext:Container>
</Center>
</ext:BorderLayout>
</Content>
</ext:Panel>
</Items>
</ext:Viewport>
</div>
</form>
</body>
</html>
DashboardXRenderPrototype.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ext.Net;
namespace DevTesting
{
public partial class DashboardXRenderPrototype : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(
string.Format(">Dashboard.Page_Load() = IsPostBack={0},IsAjaxRequest={1}", IsPostBack, X.IsAjaxRequest));
//Dynamic controls must be re-created during each request otherwise ext cannot find the direct
//method handler, if this is not done then when you fire a direct method from say..
//a button in the user control you'll get the error 'The user control with ID='xxxxx' not found'
if (this.ViewState[string.Format("{0}HasLoaded", "Container0")] != null)
this.CreateControl("Container0", "0");
if (this.ViewState[string.Format("{0}HasLoaded", "Container1")] != null)
this.CreateControl("Container1", "1");
if (this.ViewState[string.Format("{0}HasLoaded", "Container2")] != null)
this.CreateControl("Container2", "2");
if (this.ViewState[string.Format("{0}HasLoaded", "Container3")] != null)
this.CreateControl("Container3", "3");
if (this.ViewState[string.Format("{0}HasLoaded", "Container4")] != null)
this.CreateControl("Container4", "4");
}
[DirectMethod(ViewStateMode = ViewStateMode.Enabled)]
public void LoadContainer(string panelID, string containerID, string loadTimeSecs)
{
System.Diagnostics.Debug.WriteLine(
string.Format(">Dashboard.LoadContainer() = panelID={0},containerID={1}", panelID, containerID));
DashboardXRenderPrototypeControl uc = this.LoadControl("DashboardXRenderPrototypeControl.ascx") as DashboardXRenderPrototypeControl;
uc.ID = string.Format("{0}{1}", panelID, containerID);
uc.PanelID = panelID;
uc.ContainerID = Int32.Parse(containerID);
uc.LoadTimeSecs = Int32.Parse(loadTimeSecs);
Ext.Net.Panel p = Ext.Net.Utilities.ControlUtils.FindControl<Ext.Net.Panel>(this.Form, panelID);
if (p.ContentControls.Count > 0)
p.ContentControls.Clear();
p.ContentControls.Add(uc);
p.UpdateContent();
string key = string.Format("{0}HasLoaded", panelID);
this.ViewState[key] = true;
System.Diagnostics.Debug.WriteLine(string.Format("ViewState[{0}]={1}", key, this.ViewState[key]));
}
public void CreateControl(string panelID, string containerID)
{
System.Diagnostics.Debug.WriteLine(
string.Format(">Dashboard.CreateControl() = panelID={0},containerID={1}", panelID, containerID));
DashboardXRenderPrototypeControl uc = this.LoadControl("DashboardXRenderPrototypeControl.ascx") as DashboardXRenderPrototypeControl;
uc.ID = string.Format("{0}{1}", panelID, containerID);
uc.PanelID = panelID;
uc.ContainerID = Int32.Parse(containerID);
Ext.Net.Panel p = Ext.Net.Utilities.ControlUtils.FindControl<Ext.Net.Panel>(this.Form, panelID);
p.ContentControls.Add(uc);
}
protected void ReloadAllCharts(object sender, DirectEventArgs e)
{
X.Js.Call("loadContainer", new JRawValue("Container0"));
X.Js.Call("loadContainer", new JRawValue("Container1"));
X.Js.Call("loadContainer", new JRawValue("Container2"));
X.Js.Call("loadContainer", new JRawValue("Container3"));
X.Js.Call("loadContainer", new JRawValue("Container4"));
}
[DirectMethod]
public void RefreshContainer(string containerID)
{
System.Diagnostics.Debug.WriteLine(
string.Format(">Dashboard.RefreshContainer(),containerID={0}", containerID));
int id = Int32.Parse(containerID);
switch (id)
{
case 0:
X.Js.Call("loadContainer", new JRawValue("Container0"));
break;
case 1:
X.Js.Call("loadContainer", new JRawValue("Container1"));
break;
case 2:
X.Js.Call("loadContainer", new JRawValue("Container2"));
break;
case 3:
X.Js.Call("loadContainer", new JRawValue("Container3"));
break;
case 4:
X.Js.Call("loadContainer", new JRawValue("Container4"));
break;
case 5:
this.ReloadAllCharts(null, new Ext.Net.DirectEventArgs(null));
break;
}
}
}
}
DashboardXRenderPrototypeControl.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DashboardXRenderPrototypeControl.ascx.cs" Inherits="DevTesting.DashboardXRenderPrototypeControl" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<ext:Label runat="server" ID="LoadText">
</ext:Label>
<ext:TextField ID="txtReloadID" runat="server" Text="1">
</ext:TextField>
<ext:Button ID="btnReload" runat="server" Text="Reload (Enter 0-5)">
<Listeners>
<Click Handler="parent.CompanyX.RefreshContainer(#{txtReloadID}.getValue());" />
</Listeners>
</ext:Button>
<ext:Label runat="server" ID="ReloadBtnClickText">
</ext:Label>
<ext:Button runat="server" Text="Test Direct Event" ID="ControlButtonDirectEvent">
<DirectEvents>
<Click OnEvent="ControlDirectEvent"></Click>
</DirectEvents>
</ext:Button>
DashboardXRenderPrototypeControl.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ext.Net;
namespace DevTesting
{
public partial class DashboardXRenderPrototypeControl : System.Web.UI.UserControl
{
public string PanelID { get; set; }
public int ContainerID { get; set; }
public int LoadTimeSecs{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(LoadTimeSecs));
string s = string.Format("{1} Container={2} Page_Load> @ {0}", DateTime.Now.ToString("hh:mm:ss.fff"), this.ID, this.ContainerID);
System.Diagnostics.Trace.WriteLine(s);
this.LoadText.Text = string.Format(s);
}
protected void Page_PreRender(object sender, EventArgs e)
{
X.Js.AddScript(string.Format("{0}.body.unmask();", this.PanelID));
}
protected void ControlDirectEvent(object sender, DirectEventArgs e)
{
string s = string.Format(">ControlDirectEvent @ {0}, ID={1}", DateTime.Now.ToString("hh:mm:ss.fff"), this.txtReloadID.Value);
System.Diagnostics.Trace.WriteLine(s);
this.ReloadBtnClickText.Text = s;
}
}
}