In this post well look at the some Trace.axd and
Fiddler/
FireBug output to see what kind of work we are doing to generate the dynamic content inside of the modal update panel. Additionally the some modifications to the code listed
here are listed below to integrate the WebMethod dynamic contend within the scope of a ModalPopupExtender.
Right of the bat, I have to admit that using the WebMethod version's Trace.axd output compared to the UpdatePanel's Trace output is entirely unfair. The issue is that the Control creation work handled by the AjaxControlRender is not listed in the output, as it's not directly called by the request. I've added some trace logging to get a general comparison, but I' as I have Fiddler/FireBug to let me look at the wire side of things, but that said it's definitely not a good head on comparison without some better outline of the work being performed on the server. In subsequent parts of this series I'll be looking at ways to work around this so the final head to head comparisons are really worth looking at.
One other issue I want to cover before we look at some comparison result is the issues I have with building a Control for a specific Page/Pattern/Host etc. I really like the idea of truly agnostic controls. Obviously thought I'm nowhere close to that with the UserControls I'm creating for this example. Arguably the UserControls I'm creating for the WebMethod version of this example are even more offensive in this respect as the Implement a non-standard Interface
IRenderable that is very specific to the WebMethod Usage, in defense of this though I'll offer up the challenge to think about this pattern in terms of the
MVP pattern.
Okay So Here's the unfair Trace.axd output; mostly I'm looking at the timings.
This is the UpdatePanel:
Category
|
Message
|
From First(s)
|
From Last(s)
|
aspx.page
|
Begin PreInit
|
|
|
aspx.page
|
End PreInit
|
1.65969652878819E-05
|
0.000017
|
aspx.page
|
Begin Init
|
3.00660985242153E-05
|
0.000013
|
aspx.page
|
End Init
|
0.000164551652463105
|
0.000134
|
aspx.page
|
Begin InitComplete
|
0.000178510912492205
|
0.000014
|
aspx.page
|
End InitComplete
|
0.000189424651839534
|
0.000011
|
aspx.page
|
Begin LoadState
|
0.000199253377676159
|
0.000010
|
aspx.page
|
End LoadState
|
0.000386672625233839
|
0.000187
|
aspx.page
|
Begin ProcessPostData
|
0.000400530866763667
|
0.000014
|
aspx.page
|
End ProcessPostData
|
0.000635454998960715
|
0.000235
|
aspx.page
|
Begin PreLoad
|
0.000649343171897734
|
0.000014
|
aspx.page
|
End PreLoad
|
0.000659785491581792
|
0.000010
|
aspx.page
|
Begin Load
|
0.000669621700270214
|
0.000010
|
aspx.page
|
End Load
|
0.00131647682394513
|
0.000647
|
aspx.page
|
Begin ProcessPostData Second Try
|
0.0013312554562461
|
0.000015
|
aspx.page
|
End ProcessPostData Second Try
|
0.00134366202452713
|
0.000012
|
aspx.page
|
Begin Raise ChangedEvents
|
0.00135389482436084
|
0.000010
|
aspx.page
|
End Raise ChangedEvents
|
0.00137432675119518
|
0.000020
|
aspx.page
|
Begin Raise PostBackEvent
|
0.00138573435876117
|
0.000011
|
aspx.page
|
End Raise PostBackEvent
|
0.00222819496986074
|
0.000842
|
aspx.page
|
Begin LoadComplete
|
0.0022437593016005
|
0.000016
|
aspx.page
|
End LoadComplete
|
0.00226010559135315
|
0.000016
|
aspx.page
|
Begin PreRender
|
0.00227047308251923
|
0.000010
|
aspx.page
|
End PreRender
|
0.0101874949075036
|
0.007917
|
aspx.page
|
Begin PreRenderComplete
|
0.0102070064435668
|
0.000020
|
aspx.page
|
End PreRenderComplete
|
0.0103499214300561
|
0.000143
|
aspx.page
|
Begin SaveState
|
0.0110321629598836
|
0.000682
|
aspx.page
|
End SaveState
|
0.0111056483059655
|
0.000073
|
aspx.page
|
Begin SaveStateComplete
|
0.0111185749324465
|
0.000013
|
aspx.page
|
End SaveStateComplete
|
0.0111282502598212
|
0.000010
|
aspx.page
|
Begin Render
|
0.0111427931822906
|
0.000015
|
aspx.page
|
End Render
|
0.0164754138432758
|
0.005333
|
This is the WebMethod:
Category
|
Message
|
From First(s)
|
From Last(s)
|
WebMethod
|
In GetControlTwo
|
|
|
AjaxControlRender
|
Create Page
|
0.00665580507840431
|
0.006656
|
AjaxControlRender
|
Create Header
|
0.00667671982307066
|
0.000021
|
AjaxControlRender
|
Create Form
|
0.00672034147030946
|
0.000044
|
AjaxControlRender
|
Create ScriptManager
|
0.0067555223905416
|
0.000035
|
AjaxControlRender
|
Load Control: ControlTwo.ascx
|
0.00679069208640271
|
0.000035
|
AjaxControlRender
|
Add Header
|
0.0142921113457605
|
0.007501
|
AjaxControlRender
|
Add Form
|
0.0143148818531021
|
0.000023
|
AjaxControlRender
|
Add ScriptManager
|
0.0143265065600213
|
0.000012
|
AjaxControlRender
|
Add Control: ControlTwo.ascx
|
0.0143376822920997
|
0.000011
|
AjaxControlRender
|
Bind Control: ControlTwo.ascx
|
0.0143483866005953
|
0.000011
|
AjaxControlRender
|
Render Page
|
0.0145353172755542
|
0.000187
|
AjaxControlRender
|
Parse Output
|
0.0320549216788333
|
0.017520
|
AjaxControlRender
|
Render Complete
|
0.0320997405923142
|
0.000045
|
Okay, so it looks like in this very simple case the WebMethod is twice as slow as using an update panel. This certainly doesn't lend itself to recommending the additional complexity of using WebMethod's vs. UpdatePanels to add dynamic UI Elements to the client. True these timings don't indicate what's happening in the browser, but when we look at that later on, we'll see there's very little difference in what actually happens on the client. Running these tests several times, this appears to be pretty consistent. On this very simple example using a WebMethod is between 1.5 and 2 times as costly as using an UpdatePanel.
Let's open up FireBug (or Fiddler if you're using IE) and look at the request/response overhead for these 2 implementations.
UpdatePanel:
Post:
|
DataFromTwoCtldr
|
|
|
FirstLoaderTgtCtl
|
|
|
MainContentDynCtl$DataFromOne
|
Some Text For Two
|
|
MainContentDynCtl$Submit
|
Go Get ControlTwo
|
|
ScriptManager1
|
Content|MainContentDynCtl$Submit
|
|
__EVENTARGUMENT
|
|
|
__ EVENTTARGET
|
|
|
__EVENTVALIDATION
|
/wEWCQKm0JmOAwL6poiACwKYl8StBAKrg7q+DALpna34AwL3vdXbBwLy/PKFBwLn1IhgAvSRrqIN5a3XffAoph03Vng2j9DDynitk7s= |
|
__VIEWSTATE
|
/wEPDwULLTE2MjQyODE1NDIPZBYCAgMPZBYCAgsPZBYCAgUPZBYCZg9kFgICAQ9kFgJmD2QWAgIFDw8WAh4EVGV4dGRkZGRDEEbPW8ezdjRSo6G5VB/62faV+g== |
The Response:
798|updatePanel|Content|
This is the Content of ControlTwo:<br />
Put some Text Here for ControlOne:<input name="MainContentDynCtl$DataFromTwo" type="text" id="MainContentDynCtl_DataFromTwo"
/><br />
<input type="submit" name="MainContentDynCtl$Submit" value="Go Get ControlOne" id="MainContentDynCtl_Submit"
/><br />
<span id="MainContentDynCtl_TextFromControlOne">Some Text For Two</span><br />
<input type="submit" name="MainContentDynCtl$OKButton" value="OK" id="MainContentDynCtl_OKButton" />
<br />
<input type="submit" name="MainContentDynCtl$CancelButton" value="Cancel" id="MainContentDynCtl_CancelButton"
/><br />
<input type="submit" name="MainContentDynCtl$MinimizeButton" value="Minimize" id="MainContentDynCtl_MinimizeButton"
/><br />
|0|hiddenField|__EVENTTARGET||0|hiddenField|__EVENTARGUMENT||148|hiddenField
|__VIEWSTATE|/wEPDwULLTE2MjQyODE1NDIPZBYCAgMPZBYCAgsPZBYCAgUPZBYCZg9kFgICAQ9kFgJmD2QWAgIFDw8WAh4EVGV4dAURU29tZSBUZXh0IEZvciBUd29kZGTNCkz
/0eO77l1wnH0tC/vDoxkAIw==|104|hiddenField|__EVENTVALIDATION|/wEWCQL9kqD7BALqq/axDgL3vdXbBwLy/PKFBwLn1IhgAvSRrqINAvqmiIALApiXxK0EAquDur4MNSxugn064UiDt6p
//HN9TGNg+wM=|0|asyncPostBackControlIDs|||0|postBackControlIDs|||8|updatePanelIDs||tContent|0|childUpdatePanelIDs
|||7|panelsToRefreshIDs||Content|2|asyncPostBackTimeout||90|12|formAction||default.aspx|11|pageTitle
||ModalSample|247|scriptBlock|ScriptContentNoTags|function wireUpHandlers(){var extenderID = MODAL_EXTENDER_ID
;addCancelHandler('MainContentDynCtl_CancelButton', extenderID);addCancelHandler('MainContentDynCtl_MinimizeButton'
, extenderID);addOkayHandler('MainContentDynCtl_OKButton', extenderID);}|65|scriptBlock|ScriptContentNoTags
|MODAL_EXTENDER_ID = 'ModalPopup'; Sys.Application.add_load(init);|0|hiddenField|DataFromTwoCtldr||17
|hiddenField|DataFromOneCtldr|Some Text For Two|1|hiddenField|FirstLoaderTgtCtl|2|
WebMethod:
Post:
{"data":{"__type":"WebMethodWork.TextObject","TextField":"Some Text For Two"}}
Response:
\u003c!-- START --\u003e\u003cscript type=\"text/javascript\"\u003e\r\nfunction buildTextObject(){var
dataObj = new WebMethodWork.TextObject();dataObj.TextField = document.getElementById(\u0027ctl03_DataFromTwo
\u0027).value; return dataObj; }\r\n\u003c/script\u003e\r\n\r\n\r\n\r\nThis is the Content of ControlTwo
:\u003cbr /\u003e\r\nPut some Text Here for ControlOne:\u003cinput name=\"ctl03$DataFromTwo\" type=\"text
\" id=\"ctl03_DataFromTwo\" /\u003e\u003cbr /\u003e\r\n\u003cscript type=\"text/javascript\"\u003e\r
\nfunction regJS(html){\r\nwhile (html.indexOf(\u0027\u003cscript\u0027) != -1){\r\nvar scriptStart
= html.indexOf(\u0027\u003e\u0027, (html.indexOf(\u0027\u003c\u0027 + \u0027script\u0027)));\r\nvar scriptEnd
= html.indexOf(\u0027\u003c\u0027 +\u0027/script\u003e\u0027);\r\nvar script = html.substring(scriptStart
+1, scriptEnd);\r\nhtml = html.substring(0,html.indexOf(\u0027\u003c\u0027 + \u0027script\u0027)) + html
.substring(scriptEnd+9,html.length-1);\r\nvar scriptElement = document.createElement(\u0027SCRIPT\u0027
);\r\nscriptElement.type = \u0027text/javascript\u0027;\r\ndocument.getElementsByTagName(\u0027HEAD\u0027
)[0].appendChild(scriptElement);\r\nscriptElement.innerHTML = script;\r\n}\r\nreturn html;}\r\nvar SRC_TGT
= SRC_TGT;function dynControlTwoLinkResponseHandler(result){result = regJS(result);\r\nvar el = document
.getElementById(SRC_TGT); el.innerHTML = result; if(el.style.display == \u0027none\u0027) { el.style
.display = \u0027\u0027;}}\r\n\r\nfunction dynControlTwoLinkInitRequest(){PageMethods.GetControlOne(buildTextObject
(),dynControlTwoLinkResponseHandler);}\r\n\u003c/script\u003e\r\n\r\n\u003ca onclick=\"dynControlTwoLinkInitRequest
(); return false;\" id=\"ctl03_dynControlTwoLink\" href=\"javascript:__doPostBack(\u0027ctl03$dynControlTwoLink
\u0027,\u0027\u0027)\"\u003eGet Control One\u003c/a\u003e\u003cbr /\u003e\r\n\u003cspan id=\"ctl03_TextFromControlOne
\"\u003eSome Text For Two\u003c/span\u003e\u003cbr /\u003e\r\n\u003cinput type=\"submit\" name=\"ctl03$OKButton
\" value=\"OK\" id=\"ctl03_OKButton\" /\u003e\u003cbr /\u003e\r\n\u003cinput type=\"submit\" name=\"ctl03$CancelButton
\" value=\"Cancel\" id=\"ctl03_CancelButton\" /\u003e\u003cbr /\u003e\r\n\u003cinput type=\"submit\"
name=\"ctl03$MinimizeButton\" value=\"Minimize\" id=\"ctl03_MinimizeButton\" /\u003e\u003cbr /\u003e
\r\n\r\n\r\n\r\n\r\n\r\n\u003c!-- END --\u003e\r\n
Once again, we really don't see much of a benefit by using the WebMethod. The Post data is much smaller, but the Response is larger, although not by much so again, there's really not much motivation to incur the higher level of effort need to build and maintain a WebMethod driven dynamic UI.
The reality is though, that you are unlikely to ever have a page with a single control. Later in this series we're going to get a more realistic comparison between the UpdatePanel vs. WebMethod approach to managing the UI. The more I look into the dark heart that is the desktop-ing of the Web, the more I realize that the problems that developers currently face, are going to pale in comparison to the challenges they will face.
The key thing I think that one could abstract from this posting series so far is that the standard response of it's not "one size fits all" is extremely accurate when it comes to Ajax driven websites. Contrary to what most developers and development organizations like there's not an apparent de-facto standard way of approaching the UI. Each time a portion of a WebPage or WebSite is moved into the world of Ajax, the decisions of how to achieve a successful migration will need to be evaluated all over again, leading to a diverse, and potentially un- maintainable mesh of custom UI and JavaScript Code.
Most people that have done Asp.Net programming for any amount of time will not find this surprising. It's not that different than the realities faced in traditional web development. The added work here is the increase in the number of potential development languages, and platforms. Choices Like PageMethods, WebServices, using Third party webservices proxied through your own host. These aren't new concerns, only now the need to be discussed at the UI Level, and the UI is really the focus of much of design process.
Some strange hybridization of the feature focused XP approach to web and BUFD will need to be used to allow the UI to flex in the way's it needs without re-inventing the technology stack every single time… but I digress.
More to come next time, but here's the modified code for the WebMethod approach the Dynamic Modal Dialog.
Default.aspx.WebMethod.cs
public partial class _Default
{
[WebMethod]
public static string GetControlOne(TextObject data)
{
HttpContext.Current.Trace.Write("WebMethod", "In GetControlOne");
return AjaxControlRenderer.RenderAjaxControl<ControlOne, TextObject>(true, "ControlOne.ascx", data);
}
[WebMethod]
public static string GetControlTwo(TextObject data)
{
HttpContext.Current.Trace.Write("WebMethod", "In GetControlTwo");
return AjaxControlRenderer.RenderAjaxControl<ControlTwo, TextObject>(true, "ControlTwo.ascx", data);
}
}
AjaxControlRenderer
public class AjaxControlRenderer
{
public static string RenderAjaxControl<T, D>(bool enableViewState, string path, D data) where T : System.Web.UI.Control, IRenderable<D>, new()
{
TraceContext trace = HttpContext.Current.Trace;
trace.Write(category, "Create Page");
Page renderPage = new Page();
renderPage.EnableViewState = enableViewState;
trace.Write(category, "Create Header");
HtmlHead header = renderPage.LoadControl(typeof(HtmlHead), null) as HtmlHead;
header.EnableViewState = enableViewState;
trace.Write(category, "Create Form");
HtmlForm form = renderPage.LoadControl(typeof(HtmlForm), null) as HtmlForm;
form.EnableViewState = enableViewState;
trace.Write(category, "Create ScriptManager");
ScriptManager scriptManager = renderPage.LoadControl(typeof(ScriptManager), null) as ScriptManager;
trace.Write(category, "Load Control: " + path);
T controlToRender = renderPage.LoadControl(path) as T;
trace.Write(category, "Add Header");
renderPage.Controls.Add(header);
trace.Write(category, "Add Form");
renderPage.Controls.Add(form);
trace.Write(category, "Add ScriptManager");
form.Controls.Add(scriptManager);
form.Controls.Add(new LiteralControl("<!-- START -->"));
trace.Write(category, "Add Control: " + path);
form.Controls.Add(controlToRender);
form.Controls.Add(new LiteralControl("<!-- END -->"));
if (null != data)
{
trace.Write(category, "Bind Control: " + path);
controlToRender.PopulateData(data);
}
StringWriter htmlOutput = new StringWriter();
trace.Write(category, "Render Page");
HttpContext.Current.Server.Execute(renderPage, htmlOutput, false);
trace.Write(category, "Parse Output");
string result = htmlOutput.ToString();
result = result.Substring(result.IndexOf("<!-- START -->"));
result = result.Substring(0, result.IndexOf("<!-- END -->") + 14);
trace.Write(category, "Render Complete");
return result;
}
static readonly string category = "AjaxControlRenderer";
}
Default.aspx
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>WebMethod Page</title>
<style type="text/css">
body
{
font-family: Verdana, Arial;
font-size:medium;
color:#000000;
background-color:#fdfdfd;
}
.Modal
{
background-color:#AADDDD;
color:#ffffff;
}
.Modal td
{
white-space:nowrap;
text-align:center;
}
.CloseButtonStyle
{
font-size:large;
font-weight:bold;
color:#ffffff;
text-align:center;
text-decoration:none;
}
</style>
<script type="text/javascript">
function OnCanceledHandler(){
alert("Cancel Completed");
}
function OnOkayedHandler(){
alert("Okay Completed");
}
function addOkayHandler(clientID, extenderID){
var comp = Sys.Application.findComponent(extenderID);
$addHandler($get(clientID), 'click', Function.createDelegate(comp, comp._onOk));
}
function addCancelHandler(clientID, extenderID){
var comp = Sys.Application.findComponent(extenderID);
$addHandler($get(clientID), 'click', Function.createDelegate(comp, comp._onCancel));
}
function init(){
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm){
if (!prm.get_isInAsyncPostBack()){
prm.add_endRequest(endHandler);
if (wireUpHandlers){
wireUpHandlers();
}
}
}
}
function endHandler(sender,args){
wireUpHandlers();
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="MainManager" runat="server" EnablePageMethods="true" />
<div>
<asp:Button ID="ShowModal" runat="server" Text="Show The Modal" />
<asp:Button ID="DummyOkayControl" runat="server" style="display:none;" />
<ajaxToolkit:ModalPopupExtender
ID="ModalPopup"
runat="server"
TargetControlID="ShowModal"
CancelControlID="CloseButton"
OkControlID="DummyOkayControl"
OnCancelScript="OnCanceledHandler();"
OnOkScript="OnOkayedHandler();"
PopupControlID="ModalContentWrapper"
PopupDragHandleControlID="DragHandle"
RepositionMode="repositionOnWindowResize"
DropShadow="false"
>
</ajaxToolkit:ModalPopupExtender>
<asp:Panel ID="ModalContentWrapper" runat="Server">
<table width="600px" border="0" cellpadding="0" cellspacing="0" class="Modal">
<tr>
<td style="width:580px" colspan="2" class="Modal" id="DragHandle" runat="server">
<img src="images/spacer.gif" width="580px" height="20px" alt=""/>
</td>
<td style="width:20px"><asp:Linkbutton ID="CloseButton" runat="server" CssClass="CloseButtonStyle">X</asp:Linkbutton></td>
</tr>
<tr>
<td style="width:20px">
<img src="images/spacer.gif" width="20px" height="360px" alt=""/>
</td>
<td style="width:560px;">
<asp:Panel ID="Target" runat="Server" />
</td>
<td style="width:20px">
<img src="images/spacer.gif" width="20px" height="360px" alt=""/>
</td>
</tr>
<tr>
<td style="width:600px" colspan="3">
<img src="images/spacer.gif" width="600px" height="20px" alt=""/>
</td>
</tr>
</table>
</asp:Panel>
</div>
</form>
</body>
</html>
Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
//Note this is only to make it mimic the UpdatePanel for this round
//of development
protected override void OnInit(EventArgs e)
{
if (!IsPostBack)
{
Target.Controls.Add(LoadControl("/ControlOne.ascx"));
ScriptManager.RegisterClientScriptBlock( Page, Page.GetType(), "regScript", "var SRC_TGT = '" + Target.ClientID + "';",true );
}
base.OnInit(e);
}
}
ControlOne.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ControlOne.ascx.cs" Inherits="WebMethodWork.ControlOne" %>
<%@ Register Assembly="Controls" Namespace="Controls" TagPrefix="cc1" %>
<cc1:WebMethodDataTypeMapping ID="DataMapping" runat="server" MappedType="WebMethodWork.TextObject, WebMethodWork" >
<Mappings>
<cc1:Mapping ControlID="DataFromOne" MappedPropertyName="TextField" />
</Mappings>
</cc1:WebMethodDataTypeMapping>
This is the Content of ControlOne:<br />
Put some Text Here for ControlTwo:<asp:TextBox ID="DataFromOne" runat="server" /><br />
<cc1:WebMethodUIUpdateLink
ID="dynGetControlOneLink"
runat="server"
Text="Get Control Two"
DataMapControlID="DataMapping"
WebMethod="GetControlTwo"
UseParentAsTarget="true" />
<br />
<asp:Label ID="TextFromControlTwo" runat="server" /><br />
<asp:Button ID="OKButton" runat="server" Text="OK" /><br />
<asp:Button ID="CancelButton" runat="server" Text="Cancel" /><br />
<asp:Button ID="MinimizeButton" runat="server" Text="Minimize"/><br />
ControlOne.ascx.cs
public partial class ControlOne : System.Web.UI.UserControl, IRenderable<TextObject>
{
protected override void OnLoad(EventArgs e)
{
ScriptManager.RegisterClientScriptBlock(this, GetType(), "wireScripts", getWireScripts(), true);
base.OnLoad(e);
}
public void PopulateData(TextObject data)
{
TextFromControlTwo.Text = data.TextField;
}
string getWireScripts()
{
StringBuilder script = new StringBuilder();
script.Append("function wireUpHandlers(){");
script.Append("var extenderID = MODAL_EXTENDER_ID;");
script.AppendFormat("addCancelHandler('{0}', extenderID);", CancelButton.ClientID);
script.AppendFormat("addCancelHandler('{0}', extenderID);", MinimizeButton.ClientID);
script.AppendFormat("addOkayHandler('{0}', extenderID);", OKButton.ClientID);
script.Append("}");
return script.ToString();
}
}
ControlTwo.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ControlTwo.ascx.cs" Inherits="WebMethodWork.ControlTwo" %>
<%@ Register Assembly="Controls" Namespace="Controls" TagPrefix="cc1" %>
<cc1:WebMethodDataTypeMapping ID="DataMapping" runat="server" MappedType="WebMethodWork.TextObject, WebMethodWork" >
<Mappings>
<cc1:Mapping ControlID="DataFromTwo" MappedPropertyName="TextField" />
</Mappings>
</cc1:WebMethodDataTypeMapping>
This is the Content of ControlTwo:<br />
Put some Text Here for ControlOne:<asp:TextBox ID="DataFromTwo" runat="server" /><br />
<cc1:WebMethodUIUpdateLink
ID="dynControlTwoLink"
runat="server" Text="Get Control One"
DataMapControlID="DataMapping"
WebMethod="GetControlOne"
UseParentAsTarget="true" /><br />
<asp:Label ID="TextFromControlOne" runat="server" /><br />
<asp:Button ID="OKButton" runat="server" Text="OK" /><br />
<asp:Button ID="CancelButton" runat="server" Text="Cancel" /><br />
<asp:Button ID="MinimizeButton" runat="server" Text="Minimize"/><br />
ControlTwo.ascx.cs
public partial class ControlTwo : System.Web.UI.UserControl, IRenderable<TextObject>
{
protected override void OnLoad(EventArgs e)
{
ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "wireScripts", getWireScripts(), true);
base.OnLoad(e);
}
public void PopulateData(TextObject data)
{
TextFromControlOne.Text = data.TextField;
}
string getWireScripts()
{
StringBuilder script = new StringBuilder();
script.Append("function wireUpHandlers(){");
script.Append("var extenderID = MODAL_EXTENDER_ID;");
script.AppendFormat("addCancelHandler('{0}', extenderID);", CancelButton.ClientID);
script.AppendFormat("addCancelHandler('{0}', extenderID);", MinimizeButton.ClientID);
script.AppendFormat("addOkayHandler('{0}', extenderID);", OKButton.ClientID);
script.Append("}");
return script.ToString();
}
}
Print | posted on Saturday, October 13, 2007 1:19 PM