5 // Igor Zelmanovich <igorz@mainsoft.com>
6 // Marek Habersack <grendel@twistedcode.net>
8 // (C) 2007 Mainsoft, Inc. http://www.mainsoft.com
9 // (C) 2007-2010 Novell, Inc (http://novell.com/)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections.Generic;
35 using System.ComponentModel;
36 using System.Security.Permissions;
39 namespace System.Web.UI
41 [DesignerAttribute ("System.Web.UI.Design.UpdatePanelDesigner, System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
42 [DefaultPropertyAttribute ("Triggers")]
43 [ParseChildrenAttribute (true)]
44 [PersistChildrenAttribute (false)]
45 [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46 [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47 public class UpdatePanel : Control
49 sealed class SingleChildControlCollection : ControlCollection
51 public SingleChildControlCollection (Control owner)
55 internal void AddInternal (Control child)
60 public override void Add (Control child)
62 throw GetNoChildrenException ();
65 public override void AddAt (int index, Control child)
67 throw GetNoChildrenException ();
70 public override void Clear ()
72 throw GetNoChildrenException ();
75 public override void Remove (Control value)
77 throw GetNoChildrenException ();
80 public override void RemoveAt (int index)
82 throw GetNoChildrenException ();
85 InvalidOperationException GetNoChildrenException ()
87 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.");
91 ITemplate _contentTemplate;
92 Control _contentTemplateContainer;
93 UpdatePanelUpdateMode _updateMode = UpdatePanelUpdateMode.Always;
94 bool _childrenAsTriggers = true;
96 bool _inPartialRendering;
97 UpdatePanelTriggerCollection _triggers;
98 UpdatePanelRenderMode _renderMode = UpdatePanelRenderMode.Block;
99 ScriptManager _scriptManager;
100 Control cachedParent;
101 UpdatePanel parentPanel;
102 bool parentPanelChecked;
104 UpdatePanel ParentPanel {
106 Control parent = Parent;
107 if (cachedParent == parent && parentPanelChecked)
110 cachedParent = parent;
111 parentPanel = FindParentPanel (parent);
117 [Category ("Behavior")]
118 [DefaultValue (true)]
119 public bool ChildrenAsTriggers {
121 return _childrenAsTriggers;
124 _childrenAsTriggers = value;
128 [TemplateInstance (TemplateInstance.Single)]
129 [PersistenceMode (PersistenceMode.InnerProperty)]
131 public ITemplate ContentTemplate {
133 return _contentTemplate;
136 _contentTemplate = value;
141 public Control ContentTemplateContainer {
143 if (_contentTemplateContainer == null) {
144 _contentTemplateContainer = CreateContentTemplateContainer ();
145 ((SingleChildControlCollection) Controls).AddInternal (_contentTemplateContainer);
147 return _contentTemplateContainer;
151 public override sealed ControlCollection Controls {
152 get { return base.Controls; }
156 public bool IsInPartialRendering {
157 get { return _inPartialRendering; }
160 [Category ("Layout")]
161 public UpdatePanelRenderMode RenderMode {
170 protected internal virtual bool RequiresUpdate {
172 return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate || AnyTriggersFired ();
176 internal ScriptManager ScriptManager {
178 if (_scriptManager == null) {
179 _scriptManager = ScriptManager.GetCurrent (Page);
180 if (_scriptManager == null)
181 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));
183 return _scriptManager;
187 [MergableProperty (false)]
189 [PersistenceMode (PersistenceMode.InnerProperty)]
190 [Category ("Behavior")]
191 public UpdatePanelTriggerCollection Triggers {
193 if (_triggers == null)
194 _triggers = new UpdatePanelTriggerCollection (this);
199 bool AnyTriggersFired ()
201 if (_triggers == null || _triggers.Count == 0)
204 foreach (UpdatePanelTrigger trigger in _triggers)
205 if (trigger.HasTriggered ())
211 [Category ("Behavior")]
212 [DefaultValueAttribute (UpdatePanelUpdateMode.Always)]
213 public UpdatePanelUpdateMode UpdateMode {
222 // Used by nested panels (see bug #542441)
223 ScriptManager.AlternativeHtmlTextWriter RenderChildrenWriter { get; set; }
225 protected virtual Control CreateContentTemplateContainer ()
227 return new Control ();
230 protected override sealed ControlCollection CreateControlCollection ()
232 return new SingleChildControlCollection (this);
235 protected internal virtual void Initialize ()
237 int tcount = _triggers != null ? _triggers.Count : 0;
238 if (tcount == 0 || !ScriptManager.SupportsPartialRendering)
241 for (int i = 0; i < tcount; i++)
242 _triggers [i].Initialize ();
245 protected override void OnInit (EventArgs e) {
248 ScriptManager.RegisterUpdatePanel (this);
249 if (ParentPanel != null)
250 ScriptManager.RegisterChildUpdatePanel (this);
252 if (ContentTemplate != null)
253 ContentTemplate.InstantiateIn (ContentTemplateContainer);
256 protected override void OnLoad (EventArgs e) {
262 protected override void OnPreRender (EventArgs e) {
263 base.OnPreRender (e);
265 if (UpdateMode == UpdatePanelUpdateMode.Always && !ChildrenAsTriggers)
266 throw new InvalidOperationException (String.Format ("ChildrenAsTriggers cannot be set to false when UpdateMode is set to Always on UpdatePanel '{0}'", ID));
269 protected override void OnUnload (EventArgs e) {
273 protected override void Render (HtmlTextWriter writer) {
274 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
275 if (RenderMode == UpdatePanelRenderMode.Block)
276 writer.RenderBeginTag (HtmlTextWriterTag.Div);
278 writer.RenderBeginTag (HtmlTextWriterTag.Span);
279 RenderChildren (writer);
280 writer.RenderEndTag ();
283 UpdatePanel FindParentPanel (Control parent)
285 parentPanelChecked = true;
286 while (parent != null) {
287 UpdatePanel panel = parent as UpdatePanel;
291 parent = parent.Parent;
297 protected override void RenderChildren (HtmlTextWriter writer)
299 RenderChildrenWriter = null;
301 if (IsInPartialRendering) {
302 ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
303 if (altWriter == null)
304 altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
306 if (altWriter == null) {
307 UpdatePanel parentPanel = ParentPanel;
308 if (parentPanel != null)
309 altWriter = parentPanel.RenderChildrenWriter;
312 if (altWriter == null)
313 throw new InvalidOperationException ("Internal error. Invalid writer object.");
315 // Used by nested panels (see bug #542441)
316 RenderChildrenWriter = altWriter;
318 HtmlTextWriter responseOutput = altWriter.ResponseOutput;
319 StringBuilder sb = new StringBuilder ();
320 HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
321 base.RenderChildren (w);
324 if (ParentPanel != null)
325 writer.Write (sb.ToString ());
327 ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
330 RenderChildrenWriter = null;
333 base.RenderChildren (writer);
336 internal void SetInPartialRendering (bool setting)
338 _inPartialRendering = setting;
341 public void Update ()
343 if (UpdateMode == UpdatePanelUpdateMode.Always)
344 throw new InvalidOperationException ("The Update method can only be called on UpdatePanel with ID '" + ID + "' when UpdateMode is set to Conditional.");
346 _requiresUpdate = true;