2009-04-11 Marek Habersack <mhabersack@novell.com>
[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                 protected virtual Control CreateContentTemplateContainer ()
205                 {
206                         return new Control ();
207                 }
208
209                 protected override sealed ControlCollection CreateControlCollection ()
210                 {
211                         return new SingleChildControlCollection (this);
212                 }
213
214                 protected internal virtual void Initialize ()
215                 {
216                         int tcount = _triggers != null ? _triggers.Count : 0;
217                         if (tcount == 0 || !ScriptManager.SupportsPartialRendering)
218                                 return;
219                         
220                         for (int i = 0; i < tcount; i++)
221                                 _triggers [i].Initialize ();
222                 }
223
224                 protected override void OnInit (EventArgs e) {
225                         base.OnInit (e);
226
227                         ScriptManager.RegisterUpdatePanel (this);
228
229                         if (ContentTemplate != null)
230                                 ContentTemplate.InstantiateIn (ContentTemplateContainer);
231                 }
232
233                 protected override void OnLoad (EventArgs e) {
234                         base.OnLoad (e);
235
236                         Initialize ();
237                 }
238
239                 protected override void OnPreRender (EventArgs e) {
240                         base.OnPreRender (e);
241
242                         if (UpdateMode == UpdatePanelUpdateMode.Always && !ChildrenAsTriggers)
243                                 throw new InvalidOperationException (String.Format ("ChildrenAsTriggers cannot be set to false when UpdateMode is set to Always on UpdatePanel '{0}'", ID));
244                 }
245
246                 protected override void OnUnload (EventArgs e) {
247                         base.OnUnload (e);
248                 }
249
250                 protected override void Render (HtmlTextWriter writer) {
251                         writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
252                         if (RenderMode == UpdatePanelRenderMode.Block)
253                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
254                         else
255                                 writer.RenderBeginTag (HtmlTextWriterTag.Span);
256                         RenderChildren (writer);
257                         writer.RenderEndTag ();
258                 }
259
260                 protected override void RenderChildren (HtmlTextWriter writer)
261                 {
262                         if (IsInPartialRendering) {
263                                 ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
264                                 if (altWriter == null)
265                                         altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
266                                 if (altWriter == null)
267                                         throw new InvalidOperationException ("Internal error. Invalid writer object.");
268                                         
269                                 HtmlTextWriter responseOutput = altWriter.ResponseOutput;
270                                 StringBuilder sb = new StringBuilder ();
271                                 HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
272                                 base.RenderChildren (w);
273                                 w.Flush ();
274                                         
275                                 ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
276                         } else
277                                 base.RenderChildren (writer);
278                 }
279
280                 internal void SetInPartialRendering (bool setting)
281                 {
282                         _inPartialRendering = setting;
283                 }
284                 
285                 public void Update ()
286                 {
287                         if (UpdateMode == UpdatePanelUpdateMode.Always)
288                                 throw new InvalidOperationException ("The Update method can only be called on UpdatePanel with ID '" + ID + "' when UpdateMode is set to Conditional.");
289                         
290                         _requiresUpdate = true;
291                 }
292         }
293 }