Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » Ajax » General » Downloads
 
Add your own
alternative version
Go to top

Magic AJAX: Applying AJAX to your existing Web Pages

, 28 May 2007
How to apply AJAX technologies to your web pages without replacing ASP.NET controls and/or writing JavaScript code.
magicajax-030-net11.zip
magicajax
Examples
ExampleSite (.NET 2.0 only)
Web.sitemap
webparts
images
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
examples
App_Data
App_Code
Docs
Core
script
bin
MagicAjax.dll
magicajax-030-net20.zip
MagicAjax.dll
Web.sitemap
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
magicajax-030-source.zip
Web.sitemap
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
MagicAjax.snk
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
UI
Design
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Controls
ClientEventControls
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Extra
Entries.Old
Entries
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Interfaces
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Configuration
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
magicajax.zip
AJAXTest
AJAXTest.csproj.webinfo
Global.asax
Ajax
Ajax.csproj.user
Controls
Design
script
#region Copyright
/*
Copyright (C) 2005 Argiris Kirtzidis
This script is supplied "as is" without any form of warranty. I shall not be liable for
any loss or damage to person or property as a result of using this script. Use this script
at your own risk! You are licensed to use this script free of charge for commercial or
non-commercial use providing you do not remove the copyright notice or disclaimer.
*/
#endregion

using System;
using System.ComponentModel;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace Ajax.Controls
{
	/// <summary>
	/// Works like Panel but the controls it contains are rendered on the page by sending
	/// javascript to the client.
	/// </summary>
	/// <remarks>
	/// The main control that makes all the hard work for seamless AJAXing. It spots
	/// controls that are added, removed or altered, and sends the appropriate javascript
	/// for the refreshing of the page. In case it contains a RenderedByScriptControl, it
	/// ignores it and lets the RenderedByScriptControl to produce the appropriate javascript
	/// for its appearance.
	/// 
	/// If an AjaxPanel (parent) contains another AjaxPanel (child), and a control
	/// of the child-AjaxPanel is altered, parent-AjaxPanel won't send the entire html
	/// rendering of the child-AjaxPanel, but instead the child-AjaxPanel will send only
	/// the html of the altered control. Thus, the size of javascript code that the client
	/// gets as a response of a callback, is greatly reduced.
	/// 
	/// It is not necessary to put all the controls of the page inside an AjaxPanel. Only
	/// the controls that are going to be refreshed on the client using javascript are
	/// required to be contained within an AjaxPanel.
	/// </remarks>
	[Designer("Ajax.Controls.Design.AjaxPanelDesigner, Ajax"),
		ParseChildrenAttribute(false),
		PersistChildren(true),
		ToolboxData("<{0}:AjaxPanel runat=server>AjaxPanel</{0}:AjaxPanel>")]
	public class AjaxPanel : RenderedByScriptControl, IPostDataLoadedEventHandler, INamingContainer
	{
		#region Private Variables

		private bool setCallBackForChildPostBack = true;
		private bool setCallBackForSubmitButtons = true;
		private ArrayList addedControls = new ArrayList();
		private ArrayList removedControls = new ArrayList();
		private Hashtable controlHtmls = new Hashtable();
		private NoVerifyRenderingPage noVerifyPage = new NoVerifyRenderingPage();

		#endregion

		#region Constructor
		/// <summary>
		/// Creates an instance of a RenderedByScriptControl with the Span tagName.
		/// </summary>
		/// <remarks>
		/// AjaxPanel uses Span instead of Div, because ASP.NET translates Div to a
		/// table if the browser is Firefox.
		/// </remarks>
		public AjaxPanel() : base(HtmlTextWriterTag.Span)
		{
		}
		#endregion

		#region Properties

		#region SetCallBackForChildPostBack
		/// <summary>
		/// Defines whether AjaxPanel automatically replaces the "__doPostBack" function
		/// in all its child controls, with the CallBack function. Default is true.
		/// </summary>
		/// <remarks>
		/// AjaxPanel currently replaces "__doPostBack" from the entire html rendering
		/// of its child controls. i.e. it will replace "__doPostBack" even from the
		/// text property of a TextBox.
		/// If you don't want this to happen, set this property to false and put the
		/// callback function to the postback controls using code.
		/// </remarks>
		/// <example>
		/// <code>
		/// LinkButton link = new LinkButton();
		/// link.Attributes.Add(CallBackHelper.GetCallbackEventReference(link) + " return false;");
		/// ajaxPanel.Controls.Add(link);
		/// 
		/// // Disable automatic replacement of postback function
		/// ajaxPanel.SetCallBackForChildPostBack = false;
		/// </code>
		/// </example>
		[Bindable(false), Category("Behavior"), DefaultValue(true)] 
		public bool SetCallBackForChildPostBack
		{
			get { return setCallBackForChildPostBack; }
			set { setCallBackForChildPostBack = value; }
		}
		#endregion

		#region SetCallBackForSubmitButtons
		/// <summary>
		/// Defines whether AjaxPanel automatically replaces the submit function of the Button
		/// controls it contains, with a CallBack function. Default is true.
		/// </summary>
		/// <remarks>
		/// When this property is true, every button that is added to AjaxPanel will
		/// have its "onclick" attribute set to the client CallBack function.
		/// </remarks>
		[Bindable(false), Category("Behavior"), DefaultValue(true)] 
		public bool SetCallBackForSubmitButtons
		{
			get { return setCallBackForSubmitButtons; }
			set { setCallBackForSubmitButtons = value; }
		}
		#endregion

		#endregion

		#region Public Methods

		#region override RenderByScript
		/// <summary>
		/// It scans child controls for added, removed or altered controls and sends
		/// the appropriate javascript to the client.
		/// </summary>
		/// <returns>True if rendering by script was needed, False if it was not</returns>
		public override bool RenderByScript()
		{
			if ( ! base.RenderByScript() )
				return false;

			if (SetCallBackForSubmitButtons)
				PutCallBackFunctionInSubmitButtons(this);

			DisableVerifyRendering (true);

			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			HtmlTextWriter litewriter = new HtmlTextWriter(new System.IO.StringWriter(sb));

			System.Text.StringBuilder sbFull = new System.Text.StringBuilder();
			HtmlTextWriter fullwriter = new HtmlTextWriter(new System.IO.StringWriter(sbFull));

			bool allControlsAreNew = (Controls.Count == addedControls.Count);

			if ( CallBackHelper.IsCallBackStartup || allControlsAreNew )
			{
				// Render all the controls in a single html rendering.

				for (int i=0; i < Controls.Count; i++)
				{
					Control con = Controls[i];

					fullwriter.WriteBeginTag ("span");
					fullwriter.WriteAttribute ("id", GetAjaxElemID(con));
					fullwriter.Write (HtmlTextWriter.TagRightChar);

					ExtendedRenderControl (con, fullwriter, litewriter);

					fullwriter.WriteEndTag ("span");

					if (SetCallBackForChildPostBack)
						sb.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
					controlHtmls[con] = sb.ToString();
					sb.Length = 0;
				}

				if (sbFull.Length > 0)
				{
					if (SetCallBackForChildPostBack)
						sbFull.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);

					CallBackHelper.WriteSetHtmlOfElementScript (sbFull.ToString(), ClientID);
				}
			}
			else
			{
				foreach (Control con in removedControls)
				{
					controlHtmls.Remove (con);
					CallBackHelper.WriteRemoveElementScript (ClientID, GetAjaxElemID(con));
				}

				for (int i=0; i < Controls.Count; i++)
				{
					Control con = Controls[i];

					string html;
					sbFull.Length = sb.Length = 0;

					if (addedControls.Contains(con))
					{
						// It's a new control, create it on the client at the appropriate place.
						ExtendedRenderControl (con, fullwriter, litewriter);
						if (SetCallBackForChildPostBack)
						{
							sbFull.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
							sb.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
						}

						CallBackHelper.WriteAddElementScript (ClientID, "span", GetAjaxElemID(con), sbFull.ToString(), GetNextExistingElement(i));
						controlHtmls[con] = sb.ToString();
					}
					else
					{
						ExtendedRenderControl (con, litewriter);
						if (SetCallBackForChildPostBack)
							sb.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
						html = sb.ToString();
						
						// If it's html rendering is the same, ignore it.
						if (html != (string)controlHtmls[con])
						{
							ExtendedWriteSetHtmlOfElementScript (html, GetAjaxElemID(con));
							controlHtmls[con] = html;
						}
					}
				}
			}

			DisableVerifyRendering (false);

			addedControls.Clear();
			removedControls.Clear();

			return true;
		}
		#endregion

		#region RaisePostDataLoadedEvent
		/// <summary>
		/// Caches the html rendering of the post data changed controls that belong to
		/// the AjaxPanel.
		/// </summary>
		/// <remarks>
		/// If a child control is altered by post data, AjaxPanel will send the javascript
		/// to refresh the control on the page, but it is unnecessary because the control
		/// on the form doesn't need refreshing.
		/// This method caches the new html rendering of the controls that received
		/// new post data so that the AjaxPanel doesn't think that they were altered.
		/// 
		/// Called by AjaxHttpModule.
		/// </remarks>
		public virtual void RaisePostDataLoadedEvent(ReadOnlyArrayList changedControls)
		{
			ArrayList dirtyControls = new ArrayList();

			for (int i=0; i < changedControls.Count; i++)
			{
				Control control = (Control) changedControls[i];
				// The top parent of this control that belongs to this AjaxPanel
				Control panelChild = FindTopPanelChildOfControl(control);

				if (panelChild != null)
				{
					dirtyControls.Add (panelChild);
				}
			}
			
			if (dirtyControls.Count == 0)
				return;

			DisableVerifyRendering (true);

			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			HtmlTextWriter litewriter = new HtmlTextWriter(new System.IO.StringWriter(sb));

			for (int i=0; i < dirtyControls.Count; i++)
			{
				Control control = (Control) dirtyControls[i];

				ExtendedRenderControl (control, litewriter);
				if (SetCallBackForChildPostBack)
					sb.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
		
				controlHtmls[control] = sb.ToString();
				sb.Length = 0;
			}

			DisableVerifyRendering (false);
		}
		#endregion

		#region Clear
		/// <summary>
		/// It removes the child controls of the AjaxPanel without producing the 
		/// appropriate javascript to refresh the page at the client.
		/// </summary>
		public void Clear()
		{
			Controls.Clear();
			addedControls.Clear();
			removedControls.Clear();
			controlHtmls.Clear();
		}
		#endregion

		#endregion

		#region Protected Methods

		#region override AddedControl
		/// <summary>
		/// Adds the control to the added controls collection.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="index"></param>
		protected override void AddedControl(Control control, int index)
		{
			addedControls.Add (control);
			base.AddedControl (control, index);
		}
		#endregion

		#region override RemovedControl
		/// <summary>
		/// Adds the control to the removed controls collection.
		/// </summary>
		/// <param name="control"></param>
		/// <param name="index"></param>
		protected override void RemovedControl(Control control)
		{
			if (addedControls.Contains(control))
                addedControls.Remove (control);
			else
				removedControls.Add (control);

			base.RemovedControl (control);
		}
		#endregion

		#region override RenderChildren
		/// <summary>
		/// Does a normal rendering of the child controls.
		/// </summary>
		/// <remarks>
		/// Each child control is contained inside a Span tag with unique id so that
		/// it can be easily manipulated apart from the other child controls.
		/// </remarks>
		/// <param name="writer"></param>
		protected override void RenderChildren(HtmlTextWriter writer)
		{
			if (SetCallBackForSubmitButtons)
				PutCallBackFunctionInSubmitButtons(this);

			DisableVerifyRendering (true);

			System.Text.StringBuilder sbFull = new System.Text.StringBuilder();
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			HtmlTextWriter fullwriter = new HtmlTextWriter(new System.IO.StringWriter(sbFull));
			HtmlTextWriter litewriter = new HtmlTextWriter(new System.IO.StringWriter(sb));

			for (int i=0; i < Controls.Count; i++)
			{
				Control con = Controls[i];

				writer.WriteBeginTag ("span");
				writer.WriteAttribute ("id", GetAjaxElemID(con));
				writer.Write (HtmlTextWriter.TagRightChar);
		
				ExtendedRenderControl (con, fullwriter, litewriter);
				if (SetCallBackForChildPostBack)
				{
					sbFull.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
					sb.Replace("__doPostBack", CallBackHelper.CallBackClientFunction);
				}
				writer.Write (sbFull.ToString());
				controlHtmls[con] = sb.ToString();
				sbFull.Length = 0;
				sb.Length = 0;

				writer.WriteEndTag ("span");
			}

			DisableVerifyRendering (false);

			addedControls.Clear();
			removedControls.Clear();
		}
		#endregion

		#endregion

		#region Private Methods

		#region ExtendedWriteSetHtmlOfElementScript
		/// <summary>
		/// Calls the AJAXCbo.ExtendedSetHtmlOfElementScript function on the client.
		/// </summary>
		/// <remarks>
		/// It's used by RenderByScript method.
		/// 
		/// AjaxPanel doesn't include RenderedByScriptControl controls in the html rendering,
		/// to reduce the size of the javascript script sent to clients.
		/// AJAXCbo.ExtendedSetHtmlOfElementScript finds the RenderedByScriptControl controls
		/// that are missing from the html rendering, gets them from the page of the client
		/// and adds them in the appropriate place in the html rendering.
		/// </remarks>
		/// <param name="html">The html rendering of the control</param>
		/// <param name="elementID">The span element id that the control belongs to.</param>
		private void ExtendedWriteSetHtmlOfElementScript(string html, string elementID)
		{
			CallBackHelper.Write( String.Format("AJAXCbo.ExtendedSetHtmlOfElementScript({0},\"{1}\");\r\n", CallBackHelper.EncodeString(html), elementID) );
		}
		#endregion

		#region ExtendedRenderControl
		/// <summary>
		/// It renders the control but without including the html rendering of
		/// any RenderedByScriptControl controls.
		/// </summary>
		/// <remarks>
		/// It's used by RenderByScript method.
		/// </remarks>
		/// <param name="control"></param>
		/// <param name="litewriter"></param>
		private void ExtendedRenderControl(Control control, HtmlTextWriter litewriter)
		{
			RenderStartEventHandler renderStart = new RenderStartEventHandler(control_RenderStart_Abort);

			ArrayList list = FindRenderedByScriptControls(control);
			bool[] visibleProps = new bool[list.Count];
			bool[] monitorProps = new bool[list.Count];

			for (int i=0; i < list.Count; i++)
			{
				RenderedByScriptControl con = (RenderedByScriptControl) list[i];
				con.RenderStart += renderStart;
				visibleProps[i] = con.Visible;
				monitorProps[i] = con.MonitorVisibilityState;
				con.MonitorVisibilityState = false;
				con.Visible = true;
			}

			control.RenderControl (litewriter);

			for (int i=0; i < list.Count; i++)
			{
				RenderedByScriptControl con = (RenderedByScriptControl) list[i];
				con.RenderStart -= renderStart;
				con.Visible = visibleProps[i];
				con.MonitorVisibilityState = monitorProps[i];
			}

			list.Clear();
		}
		#endregion

		#region control_RenderStart_Abort
		/// <summary>
		/// It's part of the ExtendedRenderControl(Control control) method. It replaces the html rendering
		/// of a RenderedByScriptControl with a Span tag named "__ajax_rbs".
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void control_RenderStart_Abort(object sender, RenderStartEventArgs e)
		{
			RenderedByScriptControl con = (RenderedByScriptControl) sender;
			e.Writer.Write (String.Format("<span id=\"{0}$rbs\" name=\"__ajax_rbs\"><{1} id=\"{0}\"></{1}></span>", con.ClientID, con.GetTagName()));
			e.AbortRendering = true;
		}
		#endregion

		#region ExtendedRenderControl
		/// <summary>
		/// It produces the full rendering of the control and the rendering without
		/// including the html rendering of any RenderedByScriptControl controls.
		/// </summary>
		/// <remarks>
		/// It's used by RenderByScript method.
		/// </remarks>
		/// <param name="control"></param>
		/// <param name="fullwriter">The writer to use for the full rendering</param>
		/// <param name="litewriter">The writer to use for the rendering without any RenderedByScriptControl controls</param>
		private void ExtendedRenderControl(Control control, HtmlTextWriter fullwriter, HtmlTextWriter litewriter)
		{
			ExtendedTextWriter extTextWriter = new ExtendedTextWriter(fullwriter, litewriter);
			RenderStartEventHandler renderStart = new RenderStartEventHandler(extTextWriter.IRenderedByScript_RenderStart);
			EventHandler renderEnd = new EventHandler(extTextWriter.IRenderedByScript_RenderEnd);

			ArrayList list = FindRenderedByScriptControls(control);

			foreach (RenderedByScriptControl con in list)
			{
				con.RenderStart += renderStart;
				con.RenderEnd += renderEnd;
			}

            HtmlTextWriter extwriter = new HtmlTextWriter(extTextWriter);
			control.RenderControl (extwriter);

			foreach (RenderedByScriptControl con in list)
			{
				con.RenderStart -= renderStart;
				con.RenderEnd -= renderEnd;
			}

			list.Clear();
		}
		#endregion

		#region PutCallBackFunctionInSubmitButtons
        /// <summary>
		/// Puts the CallBack function at the onclick event of the children of
		/// the supplied control if they are submit buttons.
		/// </summary>
        /// <param name="control"></param>
		private void PutCallBackFunctionInSubmitButtons(Control control)
		{
			for (int i=0; i < control.Controls.Count; i++)
			{
				Control con = control.Controls[i];

				if (con is RenderedByScriptControl)
				{
					continue;
				}
				else if (con is Button)
				{
					((Button)con).Attributes["onclick"] = CallBackHelper.GetCallbackEventReference(con) + " return false;";
				}
				else if (con is HtmlInputControl
					&& ((HtmlInputControl)con).Type == "submit")
				{
					((HtmlInputControl)con).Attributes["onclick"] = CallBackHelper.GetCallbackEventReference(con) + " return false;";
				}
				else
					PutCallBackFunctionInSubmitButtons (con);
			}
		}
		#endregion

		#region DisableVerifyRendering
		/// <summary>
		/// Disables the verify rendering in server form check.
		/// </summary>
		/// <remarks>
		/// It disables the verify rendering in server form check of the controls by
		/// setting NoVerifyRenderingPage to their Page property. It enables it again
		/// by setting back the Page of AjaxPanel.
		/// 
		/// See the remarks of the NoVerifyRenderingPage class.
		/// </remarks>
		/// <param name="disable">True to set the NoVerifyRenderingPage, false to set the previous page back</param>
		private void DisableVerifyRendering(bool disable)
		{
			Page page = (disable) ? noVerifyPage : this.Page;
			for (int i=0; i < Controls.Count; i++)
			{
				SetPageForControl(page, Controls[i]);
			}
		}
		#endregion

		#region SetPageForControl
		/// <summary>
		/// Sets the supplied page to the Page property of the supplied control and
		/// its children.
		/// </summary>
		/// <remarks>
		/// If it encounters a RenderedByScriptControl control, it ignores it.
		/// 
		/// Called by DisableVerifyRendering.
		/// </remarks>
		/// <param name="page"></param>
		/// <param name="control"></param>
		private void SetPageForControl(Page page, Control control)
		{
			if (!(control is RenderedByScriptControl))
			{
				control.Page = page;
				for (int i=0; i < control.Controls.Count; i++)
					SetPageForControl (page, control.Controls[i]);
			}
		}
		#endregion

		#region FindTopPanelChildOfControl
		/// <summary>
		/// It returns the top parent control of the supplied control, that is an immediate
		/// child of this AjaxPanel. If the supplied control is contained inside another
		/// AjaxPanel, it returns null.
		/// </summary>
		/// <remarks>
		/// Called by RaisePostDataLoadedEvent.
		/// </remarks>
		/// <param name="control"></param>
		/// <returns></returns>
		private Control FindTopPanelChildOfControl(Control control)
		{
			if (control.Parent == null)
				return null;
			else if (control.Parent == this)
				return control;
			else if (control.Parent is AjaxPanel)
				return null;
			else
				return FindTopPanelChildOfControl(control.Parent);
		}
		#endregion

		#region FindRenderedByScriptControls
		/// <summary>
		/// It returns an ArrayList of all the RenderedByScriptControl controls that
		/// the supplied control contains.
		/// </summary>
		/// <remarks>
		/// It's used by the ExtendedRenderControl methods.
		/// </remarks>
		/// <param name="control"></param>
		/// <returns></returns>
		private ArrayList FindRenderedByScriptControls (Control control)
		{
			ArrayList list = new ArrayList();

			if (control is RenderedByScriptControl)
			{
				list.Add (control);
			}
			else
			{
				for (int i=0; i < control.Controls.Count; i++)
					list.AddRange (FindRenderedByScriptControls(control.Controls[i]));
			}

			return list;
		}
		#endregion

		#region GetNextExistingElement
		/// <summary>
		/// It returns the next control that is available at the page of the client
		/// so that a new control can be added before it.
		/// </summary>
		/// <remarks>
		/// It's used by the RenderByScript method.
		/// 
		/// It checks to see if the html rendering of the control is stored to determine
		/// whether the control exists on the page or not.
		/// </remarks>
		/// <param name="start">The index position to start searching</param>
		/// <returns></returns>
		private string GetNextExistingElement(int start)
		{
			for (int i=start+1; i < Controls.Count; i++)
			{
				Control con = Controls[i];
				if (!addedControls.Contains(con) && controlHtmls[con] != null)
					return GetAjaxElemID(con);
			}

			return null;
		}
		#endregion

		#region GetAjaxElemID
		/// <summary>
		/// It returns the Span tag id that contains the supplied control.
		/// </summary>
		/// <param name="control"></param>
		/// <returns></returns>
		private static string GetAjaxElemID(Control control)
		{
			return control.ClientID + "$ajaxdest";
		}
		#endregion

		#endregion

		#region Private Class ExtendedTextWriter
		/// <summary>
		/// It enables simultaneous rendering of full rendering and rendering without
		/// including the html rendering of any RenderedByScriptControl controls.
		/// </summary>
		/// <remarks>
		/// It's used by ExtendedRenderControl(Control, HtmlTextWriter, HtmlTextWriter).
		/// </remarks>
		private class ExtendedTextWriter : System.IO.TextWriter
		{
			private HtmlTextWriter fullwriter, litewriter;
			private bool onlyFullRender = false;

			public override System.Text.Encoding Encoding
			{
				get { return null; }
			}

			public void IRenderedByScript_RenderStart(object sender, RenderStartEventArgs e)
			{
				RenderedByScriptControl con = (RenderedByScriptControl) sender;
				Write (String.Format("<span id=\"{0}$rbs\" name=\"__ajax_rbs\">", con.ClientID));
				onlyFullRender = true;
				litewriter.Write (String.Format("<{0} id=\"{1}\">", con.GetTagName(), con.ClientID));
			}

			public void IRenderedByScript_RenderEnd(object sender, System.EventArgs e)
			{
				RenderedByScriptControl con = (RenderedByScriptControl) sender;
				litewriter.Write (String.Format("</{0}>", con.GetTagName()));
				onlyFullRender = false;
				Write ("</span>");
			}

			public ExtendedTextWriter(HtmlTextWriter fullwriter, HtmlTextWriter litewriter) : base(null)
			{
				this.fullwriter = fullwriter;
				this.litewriter = litewriter;
			}

			#region Overrides of TextWriter
			public override void Write(bool value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(char value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(char[] buffer)
			{
				fullwriter.Write (buffer);
				if (!onlyFullRender)
					litewriter.Write (buffer);
			}
			public override void Write(char[] buffer, int index, int count)
			{
				fullwriter.Write (buffer, index, count);
				if (!onlyFullRender)
					litewriter.Write (buffer, index, count);
			}
			public override void Write(decimal value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(double value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(float value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(int value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(long value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(object value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(string format, object arg0)
			{
				fullwriter.Write (format, arg0);
				if (!onlyFullRender)
					litewriter.Write (format, arg0);
			}
			public override void Write(string format, object arg0, object arg1)
			{
				fullwriter.Write (format, arg0, arg1);
				if (!onlyFullRender)
					litewriter.Write (format, arg0, arg1);
			}
			public override void Write(string format, object arg0, object arg1, object arg2)
			{
				fullwriter.Write (format, arg0, arg1, arg2);
				if (!onlyFullRender)
					litewriter.Write (format, arg0, arg1, arg2);
			}
			public override void Write(string format, params object[] arg)
			{
				fullwriter.Write (format, arg);
				if (!onlyFullRender)
					litewriter.Write (format, arg);
			}
			public override void Write(string value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(uint value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			public override void Write(ulong value)
			{
				fullwriter.Write (value);
				if (!onlyFullRender)
					litewriter.Write (value);
			}
			#endregion
		}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

Argiris Kirtzidis
Web Developer
Greece Greece
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 28 May 2007
Article Copyright 2005 by Argiris Kirtzidis
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid