Debugging cwls begone
[mono.git] / mcs / class / System.Web.Extensions / System.Web.UI / UpdatePanel.cs
1 //
2 // UpdatePanel.cs
3 //
4 // Author:
5 //   Igor Zelmanovich <igorz@mainsoft.com>
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
30 using System;
31 using System.Collections.Generic;
32 using System.Text;
33 using System.ComponentModel;
34 using System.Security.Permissions;
35 using System.IO;
36
37 namespace System.Web.UI
38 {
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
46         {
47                 sealed class SingleChildControlCollection : ControlCollection
48                 {
49                         public SingleChildControlCollection (Control owner)
50                                 : base (owner)
51                         {}
52
53                         internal void AddInternal (Control child)
54                         {
55                                 base.Add (child);
56                         }
57                         
58                         public override void Add (Control child)
59                         {
60                                 throw GetNoChildrenException ();
61                         }
62
63                         public override void AddAt (int index, Control child)
64                         {
65                                 throw GetNoChildrenException ();
66                         }
67
68                         public override void Clear ()
69                         {
70                                 throw GetNoChildrenException ();
71                         }
72
73                         public override void Remove (Control value)
74                         {
75                                 throw GetNoChildrenException ();
76                         }
77
78                         public override void RemoveAt (int index)
79                         {
80                                 throw GetNoChildrenException ();
81                         }
82                         
83                         InvalidOperationException GetNoChildrenException ()
84                         {
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.");
86                         }
87                 }
88                 
89                 ITemplate _contentTemplate;
90                 Control _contentTemplateContainer;
91                 UpdatePanelUpdateMode _updateMode = UpdatePanelUpdateMode.Always;
92                 bool _childrenAsTriggers = true;
93                 bool _requiresUpdate;
94                 bool _inPartialRendering;
95                 UpdatePanelTriggerCollection _triggers;
96                 UpdatePanelRenderMode _renderMode = UpdatePanelRenderMode.Block;
97                 ScriptManager _scriptManager;
98                 
99                 [Category ("Behavior")]
100                 [DefaultValue (true)]
101                 public bool ChildrenAsTriggers {
102                         get {
103                                 return _childrenAsTriggers;
104                         }
105                         set {
106                                 _childrenAsTriggers = value;
107                         }
108                 }
109
110                 [TemplateInstance (TemplateInstance.Single)]
111                 [PersistenceMode (PersistenceMode.InnerProperty)]
112                 [Browsable (false)]
113                 public ITemplate ContentTemplate {
114                         get {
115                                 return _contentTemplate;
116                         }
117                         set {
118                                 _contentTemplate = value;
119                         }
120                 }
121
122                 [Browsable (false)]
123                 public Control ContentTemplateContainer {
124                         get {
125                                 if (_contentTemplateContainer == null) {
126                                         _contentTemplateContainer = CreateContentTemplateContainer ();
127                                         ((SingleChildControlCollection) Controls).AddInternal (_contentTemplateContainer);
128                                 }
129                                 return _contentTemplateContainer;
130                         }
131                 }
132
133                 public override sealed ControlCollection Controls {
134                         get { return base.Controls; }
135                 }
136
137                 [Browsable (false)]
138                 public bool IsInPartialRendering {
139                         get { return _inPartialRendering; }
140                 }
141
142                 [Category ("Layout")]
143                 public UpdatePanelRenderMode RenderMode {
144                         get {
145                                 return _renderMode;
146                         }
147                         set {
148                                 _renderMode = value;
149                         }
150                 }
151
152                 protected internal virtual bool RequiresUpdate {
153                         get {
154                                 return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate || AnyTriggersFired ();
155                         }
156                 }
157
158                 internal ScriptManager ScriptManager {
159                         get {
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));
164                                 }
165                                 return _scriptManager;
166                         }
167                 }
168
169                 [MergableProperty (false)]
170                 [DefaultValue ("")]
171                 [PersistenceMode (PersistenceMode.InnerProperty)]
172                 [Category ("Behavior")]
173                 public UpdatePanelTriggerCollection Triggers {
174                         get {
175                                 if (_triggers == null)
176                                         _triggers = new UpdatePanelTriggerCollection (this);
177                                 return _triggers;
178                         }
179                 }
180
181                 bool AnyTriggersFired ()
182                 {
183                         if (_triggers == null || _triggers.Count == 0)
184                                 return false;
185
186                         foreach (UpdatePanelTrigger trigger in _triggers)
187                                 if (trigger.HasTriggered ())
188                                         return true;
189
190                         return false;
191                 }
192                 
193                 [Category ("Behavior")]
194                 [DefaultValueAttribute (UpdatePanelUpdateMode.Always)]
195                 public UpdatePanelUpdateMode UpdateMode {
196                         get {
197                                 return _updateMode;
198                         }
199                         set {
200                                 _updateMode = value;
201                         }
202                 }
203
204                 // Used by nested panels (see bug #542441)
205                 ScriptManager.AlternativeHtmlTextWriter RenderChildrenWriter { get; set; }
206                 
207                 protected virtual Control CreateContentTemplateContainer ()
208                 {
209                         return new Control ();
210                 }
211
212                 protected override sealed ControlCollection CreateControlCollection ()
213                 {
214                         return new SingleChildControlCollection (this);
215                 }
216
217                 protected internal virtual void Initialize ()
218                 {
219                         int tcount = _triggers != null ? _triggers.Count : 0;
220                         if (tcount == 0 || !ScriptManager.SupportsPartialRendering)
221                                 return;
222                         
223                         for (int i = 0; i < tcount; i++)
224                                 _triggers [i].Initialize ();
225                 }
226
227                 protected override void OnInit (EventArgs e) {
228                         base.OnInit (e);
229
230                         ScriptManager.RegisterUpdatePanel (this);
231
232                         if (ContentTemplate != null)
233                                 ContentTemplate.InstantiateIn (ContentTemplateContainer);
234                 }
235
236                 protected override void OnLoad (EventArgs e) {
237                         base.OnLoad (e);
238
239                         Initialize ();
240                 }
241
242                 protected override void OnPreRender (EventArgs e) {
243                         base.OnPreRender (e);
244
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));
247                 }
248
249                 protected override void OnUnload (EventArgs e) {
250                         base.OnUnload (e);
251                 }
252
253                 protected override void Render (HtmlTextWriter writer) {
254                         writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
255                         if (RenderMode == UpdatePanelRenderMode.Block)
256                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
257                         else
258                                 writer.RenderBeginTag (HtmlTextWriterTag.Span);
259                         RenderChildren (writer);
260                         writer.RenderEndTag ();
261                 }
262
263                 UpdatePanel FindParentPanel ()
264                 {
265                         Control parent = Parent;
266                         while (parent != null) {
267                                 UpdatePanel panel = parent as UpdatePanel;
268                                 if (panel != null)
269                                         return panel;
270
271                                 parent = parent.Parent;
272                         }
273
274                         return null;
275                 }
276                 
277                 protected override void RenderChildren (HtmlTextWriter writer)
278                 {
279                         RenderChildrenWriter = null;
280                         
281                         if (IsInPartialRendering) {
282                                 ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
283                                 if (altWriter == null)
284                                         altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
285                                 
286                                 if (altWriter == null) {
287                                         UpdatePanel parentPanel = FindParentPanel ();
288                                         if (parentPanel != null)
289                                                 altWriter = parentPanel.RenderChildrenWriter;
290                                 }
291
292                                 if (altWriter == null)
293                                         throw new InvalidOperationException ("Internal error. Invalid writer object.");
294
295                                 // Used by nested panels (see bug #542441)
296                                 RenderChildrenWriter = altWriter;
297                                 try {
298                                         HtmlTextWriter responseOutput = altWriter.ResponseOutput;
299                                         StringBuilder sb = new StringBuilder ();
300                                         HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
301                                         base.RenderChildren (w);
302                                         w.Flush ();
303                                         ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
304                                 } finally {
305                                         RenderChildrenWriter = null;
306                                 }
307                         } else
308                                 base.RenderChildren (writer);
309                 }
310
311                 internal void SetInPartialRendering (bool setting)
312                 {
313                         _inPartialRendering = setting;
314                 }
315                 
316                 public void Update ()
317                 {
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.");
320                         
321                         _requiresUpdate = true;
322                 }
323         }
324 }