5 // Igor Zelmanovich <igorz@mainsoft.com>
7 // (C) 2007 Mainsoft, Inc. http://www.mainsoft.com
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
31 using System.Collections.Generic;
33 using System.ComponentModel;
34 using System.Security.Permissions;
37 namespace System.Web.UI
39 [DesignerAttribute ("System.Web.UI.Design.UpdatePanelDesigner, System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
40 [DefaultPropertyAttribute ("Triggers")]
41 [ParseChildrenAttribute (true)]
42 [PersistChildrenAttribute (false)]
43 [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
44 [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45 public class UpdatePanel : Control
47 sealed class SingleChildControlCollection : ControlCollection
49 public SingleChildControlCollection (Control owner)
53 internal void AddInternal (Control child)
58 public override void Add (Control child)
60 throw GetNoChildrenException ();
63 public override void AddAt (int index, Control child)
65 throw GetNoChildrenException ();
68 public override void Clear ()
70 throw GetNoChildrenException ();
73 public override void Remove (Control value)
75 throw GetNoChildrenException ();
78 public override void RemoveAt (int index)
80 throw GetNoChildrenException ();
83 InvalidOperationException GetNoChildrenException ()
85 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.");
89 ITemplate _contentTemplate;
90 Control _contentTemplateContainer;
91 UpdatePanelUpdateMode _updateMode = UpdatePanelUpdateMode.Always;
92 bool _childrenAsTriggers = true;
94 bool _inPartialRendering;
95 UpdatePanelTriggerCollection _triggers;
96 UpdatePanelRenderMode _renderMode = UpdatePanelRenderMode.Block;
97 ScriptManager _scriptManager;
99 [Category ("Behavior")]
100 [DefaultValue (true)]
101 public bool ChildrenAsTriggers {
103 return _childrenAsTriggers;
106 _childrenAsTriggers = value;
110 [TemplateInstance (TemplateInstance.Single)]
111 [PersistenceMode (PersistenceMode.InnerProperty)]
113 public ITemplate ContentTemplate {
115 return _contentTemplate;
118 _contentTemplate = value;
123 public Control ContentTemplateContainer {
125 if (_contentTemplateContainer == null) {
126 _contentTemplateContainer = CreateContentTemplateContainer ();
127 ((SingleChildControlCollection) Controls).AddInternal (_contentTemplateContainer);
129 return _contentTemplateContainer;
133 public override sealed ControlCollection Controls {
134 get { return base.Controls; }
138 public bool IsInPartialRendering {
139 get { return _inPartialRendering; }
142 [Category ("Layout")]
143 public UpdatePanelRenderMode RenderMode {
152 protected internal virtual bool RequiresUpdate {
154 return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate || AnyTriggersFired ();
158 internal ScriptManager ScriptManager {
160 if (_scriptManager == null) {
161 _scriptManager = ScriptManager.GetCurrent (Page);
162 if (_scriptManager == null)
163 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));
165 return _scriptManager;
169 [MergableProperty (false)]
171 [PersistenceMode (PersistenceMode.InnerProperty)]
172 [Category ("Behavior")]
173 public UpdatePanelTriggerCollection Triggers {
175 if (_triggers == null)
176 _triggers = new UpdatePanelTriggerCollection (this);
181 bool AnyTriggersFired ()
183 if (_triggers == null || _triggers.Count == 0)
186 foreach (UpdatePanelTrigger trigger in _triggers)
187 if (trigger.HasTriggered ())
193 [Category ("Behavior")]
194 [DefaultValueAttribute (UpdatePanelUpdateMode.Always)]
195 public UpdatePanelUpdateMode UpdateMode {
204 // Used by nested panels (see bug #542441)
205 ScriptManager.AlternativeHtmlTextWriter RenderChildrenWriter { get; set; }
207 protected virtual Control CreateContentTemplateContainer ()
209 return new Control ();
212 protected override sealed ControlCollection CreateControlCollection ()
214 return new SingleChildControlCollection (this);
217 protected internal virtual void Initialize ()
219 int tcount = _triggers != null ? _triggers.Count : 0;
220 if (tcount == 0 || !ScriptManager.SupportsPartialRendering)
223 for (int i = 0; i < tcount; i++)
224 _triggers [i].Initialize ();
227 protected override void OnInit (EventArgs e) {
230 ScriptManager.RegisterUpdatePanel (this);
232 if (ContentTemplate != null)
233 ContentTemplate.InstantiateIn (ContentTemplateContainer);
236 protected override void OnLoad (EventArgs e) {
242 protected override void OnPreRender (EventArgs e) {
243 base.OnPreRender (e);
245 if (UpdateMode == UpdatePanelUpdateMode.Always && !ChildrenAsTriggers)
246 throw new InvalidOperationException (String.Format ("ChildrenAsTriggers cannot be set to false when UpdateMode is set to Always on UpdatePanel '{0}'", ID));
249 protected override void OnUnload (EventArgs e) {
253 protected override void Render (HtmlTextWriter writer) {
254 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
255 if (RenderMode == UpdatePanelRenderMode.Block)
256 writer.RenderBeginTag (HtmlTextWriterTag.Div);
258 writer.RenderBeginTag (HtmlTextWriterTag.Span);
259 RenderChildren (writer);
260 writer.RenderEndTag ();
263 UpdatePanel FindParentPanel ()
265 Control parent = Parent;
266 while (parent != null) {
267 UpdatePanel panel = parent as UpdatePanel;
271 parent = parent.Parent;
277 protected override void RenderChildren (HtmlTextWriter writer)
279 RenderChildrenWriter = null;
281 if (IsInPartialRendering) {
282 ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
283 if (altWriter == null)
284 altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
286 if (altWriter == null) {
287 UpdatePanel parentPanel = FindParentPanel ();
288 if (parentPanel != null)
289 altWriter = parentPanel.RenderChildrenWriter;
292 if (altWriter == null)
293 throw new InvalidOperationException ("Internal error. Invalid writer object.");
295 // Used by nested panels (see bug #542441)
296 RenderChildrenWriter = altWriter;
298 HtmlTextWriter responseOutput = altWriter.ResponseOutput;
299 StringBuilder sb = new StringBuilder ();
300 HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
301 base.RenderChildren (w);
303 ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
305 RenderChildrenWriter = null;
308 base.RenderChildren (writer);
311 internal void SetInPartialRendering (bool setting)
313 _inPartialRendering = setting;
316 public void Update ()
318 if (UpdateMode == UpdatePanelUpdateMode.Always)
319 throw new InvalidOperationException ("The Update method can only be called on UpdatePanel with ID '" + ID + "' when UpdateMode is set to Conditional.");
321 _requiresUpdate = true;