UpdatePanel.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // UpdatePanel.cs
  3. //
  4. // Author:
  5. // Igor Zelmanovich <[email protected]>
  6. //
  7. // (C) 2007 Mainsoft, Inc. http://www.mainsoft.com
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Collections.Generic;
  31. using System.Text;
  32. using System.ComponentModel;
  33. using System.Security.Permissions;
  34. using System.IO;
  35. namespace System.Web.UI
  36. {
  37. [DesignerAttribute ("System.Web.UI.Design.UpdatePanelDesigner, System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
  38. [DefaultPropertyAttribute ("Triggers")]
  39. [ParseChildrenAttribute (true)]
  40. [PersistChildrenAttribute (false)]
  41. [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  42. [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  43. public class UpdatePanel : Control
  44. {
  45. sealed class SingleChildControlCollection : ControlCollection
  46. {
  47. public SingleChildControlCollection (Control owner)
  48. : base (owner)
  49. {}
  50. internal void AddInternal (Control child)
  51. {
  52. base.Add (child);
  53. }
  54. public override void Add (Control child)
  55. {
  56. throw GetNoChildrenException ();
  57. }
  58. public override void AddAt (int index, Control child)
  59. {
  60. throw GetNoChildrenException ();
  61. }
  62. public override void Clear ()
  63. {
  64. throw GetNoChildrenException ();
  65. }
  66. public override void Remove (Control value)
  67. {
  68. throw GetNoChildrenException ();
  69. }
  70. public override void RemoveAt (int index)
  71. {
  72. throw GetNoChildrenException ();
  73. }
  74. InvalidOperationException GetNoChildrenException ()
  75. {
  76. return new InvalidOperationException ("The Controls property of UpdatePanel with ID '" + Owner.ID + "' cannot be modified directly. To change the contents of the UpdatePanel modify the child controls of the ContentTemplateContainer property.");
  77. }
  78. }
  79. ITemplate _contentTemplate;
  80. Control _contentTemplateContainer;
  81. UpdatePanelUpdateMode _updateMode = UpdatePanelUpdateMode.Always;
  82. bool _childrenAsTriggers = true;
  83. bool _requiresUpdate;
  84. bool _inPartialRendering;
  85. UpdatePanelTriggerCollection _triggers;
  86. UpdatePanelRenderMode _renderMode = UpdatePanelRenderMode.Block;
  87. ScriptManager _scriptManager;
  88. [Category ("Behavior")]
  89. [DefaultValue (true)]
  90. public bool ChildrenAsTriggers {
  91. get {
  92. return _childrenAsTriggers;
  93. }
  94. set {
  95. _childrenAsTriggers = value;
  96. }
  97. }
  98. [TemplateInstance (TemplateInstance.Single)]
  99. [PersistenceMode (PersistenceMode.InnerProperty)]
  100. [Browsable (false)]
  101. public ITemplate ContentTemplate {
  102. get {
  103. return _contentTemplate;
  104. }
  105. set {
  106. _contentTemplate = value;
  107. }
  108. }
  109. [Browsable (false)]
  110. public Control ContentTemplateContainer {
  111. get {
  112. if (_contentTemplateContainer == null) {
  113. _contentTemplateContainer = CreateContentTemplateContainer ();
  114. ((SingleChildControlCollection) Controls).AddInternal (_contentTemplateContainer);
  115. }
  116. return _contentTemplateContainer;
  117. }
  118. }
  119. public override sealed ControlCollection Controls {
  120. get { return base.Controls; }
  121. }
  122. [Browsable (false)]
  123. public bool IsInPartialRendering {
  124. get { return _inPartialRendering; }
  125. }
  126. [Category ("Layout")]
  127. public UpdatePanelRenderMode RenderMode {
  128. get {
  129. return _renderMode;
  130. }
  131. set {
  132. _renderMode = value;
  133. }
  134. }
  135. protected internal virtual bool RequiresUpdate {
  136. get {
  137. return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate || AnyTriggersFired ();
  138. }
  139. }
  140. internal ScriptManager ScriptManager {
  141. get {
  142. if (_scriptManager == null) {
  143. _scriptManager = ScriptManager.GetCurrent (Page);
  144. if (_scriptManager == null)
  145. throw new InvalidOperationException (String.Format ("The control with ID '{0}' requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it.", ID));
  146. }
  147. return _scriptManager;
  148. }
  149. }
  150. [MergableProperty (false)]
  151. [DefaultValue ("")]
  152. [PersistenceMode (PersistenceMode.InnerProperty)]
  153. [Category ("Behavior")]
  154. public UpdatePanelTriggerCollection Triggers {
  155. get {
  156. if (_triggers == null)
  157. _triggers = new UpdatePanelTriggerCollection (this);
  158. return _triggers;
  159. }
  160. }
  161. bool AnyTriggersFired ()
  162. {
  163. if (_triggers == null || _triggers.Count == 0)
  164. return false;
  165. foreach (UpdatePanelTrigger trigger in _triggers)
  166. if (trigger.HasTriggered ())
  167. return true;
  168. return false;
  169. }
  170. [Category ("Behavior")]
  171. [DefaultValueAttribute (UpdatePanelUpdateMode.Always)]
  172. public UpdatePanelUpdateMode UpdateMode {
  173. get {
  174. return _updateMode;
  175. }
  176. set {
  177. _updateMode = value;
  178. }
  179. }
  180. // Used by nested panels (see bug #542441)
  181. ScriptManager.AlternativeHtmlTextWriter RenderChildrenWriter { get; set; }
  182. protected virtual Control CreateContentTemplateContainer ()
  183. {
  184. return new Control ();
  185. }
  186. protected override sealed ControlCollection CreateControlCollection ()
  187. {
  188. return new SingleChildControlCollection (this);
  189. }
  190. protected internal virtual void Initialize ()
  191. {
  192. int tcount = _triggers != null ? _triggers.Count : 0;
  193. if (tcount == 0 || !ScriptManager.SupportsPartialRendering)
  194. return;
  195. for (int i = 0; i < tcount; i++)
  196. _triggers [i].Initialize ();
  197. }
  198. protected override void OnInit (EventArgs e) {
  199. base.OnInit (e);
  200. ScriptManager.RegisterUpdatePanel (this);
  201. if (ContentTemplate != null)
  202. ContentTemplate.InstantiateIn (ContentTemplateContainer);
  203. }
  204. protected override void OnLoad (EventArgs e) {
  205. base.OnLoad (e);
  206. Initialize ();
  207. }
  208. protected override void OnPreRender (EventArgs e) {
  209. base.OnPreRender (e);
  210. if (UpdateMode == UpdatePanelUpdateMode.Always && !ChildrenAsTriggers)
  211. throw new InvalidOperationException (String.Format ("ChildrenAsTriggers cannot be set to false when UpdateMode is set to Always on UpdatePanel '{0}'", ID));
  212. }
  213. protected override void OnUnload (EventArgs e) {
  214. base.OnUnload (e);
  215. }
  216. protected override void Render (HtmlTextWriter writer) {
  217. writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
  218. if (RenderMode == UpdatePanelRenderMode.Block)
  219. writer.RenderBeginTag (HtmlTextWriterTag.Div);
  220. else
  221. writer.RenderBeginTag (HtmlTextWriterTag.Span);
  222. RenderChildren (writer);
  223. writer.RenderEndTag ();
  224. }
  225. UpdatePanel FindParentPanel ()
  226. {
  227. Control parent = Parent;
  228. while (parent != null) {
  229. UpdatePanel panel = parent as UpdatePanel;
  230. if (panel != null)
  231. return panel;
  232. parent = parent.Parent;
  233. }
  234. return null;
  235. }
  236. protected override void RenderChildren (HtmlTextWriter writer)
  237. {
  238. RenderChildrenWriter = null;
  239. if (IsInPartialRendering) {
  240. ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
  241. if (altWriter == null)
  242. altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
  243. if (altWriter == null) {
  244. UpdatePanel parentPanel = FindParentPanel ();
  245. if (parentPanel != null)
  246. altWriter = parentPanel.RenderChildrenWriter;
  247. }
  248. if (altWriter == null) {
  249. Console.WriteLine (Environment.StackTrace);
  250. throw new InvalidOperationException ("Internal error. Invalid writer object.");
  251. }
  252. // Used by nested panels (see bug #542441)
  253. RenderChildrenWriter = altWriter;
  254. try {
  255. HtmlTextWriter responseOutput = altWriter.ResponseOutput;
  256. StringBuilder sb = new StringBuilder ();
  257. HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
  258. base.RenderChildren (w);
  259. w.Flush ();
  260. ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
  261. } finally {
  262. RenderChildrenWriter = null;
  263. }
  264. } else
  265. base.RenderChildren (writer);
  266. }
  267. internal void SetInPartialRendering (bool setting)
  268. {
  269. _inPartialRendering = setting;
  270. }
  271. public void Update ()
  272. {
  273. if (UpdateMode == UpdatePanelUpdateMode.Always)
  274. throw new InvalidOperationException ("The Update method can only be called on UpdatePanel with ID '" + ID + "' when UpdateMode is set to Conditional.");
  275. _requiresUpdate = true;
  276. }
  277. }
  278. }