//
// UpdatePanel.cs
//
-// Author:
+// Authors:
// Igor Zelmanovich <igorz@mainsoft.com>
+// Marek Habersack <grendel@twistedcode.net>
//
// (C) 2007 Mainsoft, Inc. http://www.mainsoft.com
+// (C) 2007-2010 Novell, Inc (http://novell.com/)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
[AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class UpdatePanel : Control
{
+ sealed class SingleChildControlCollection : ControlCollection
+ {
+ public SingleChildControlCollection (Control owner)
+ : base (owner)
+ {}
+
+ internal void AddInternal (Control child)
+ {
+ base.Add (child);
+ }
+
+ public override void Add (Control child)
+ {
+ throw GetNoChildrenException ();
+ }
+
+ public override void AddAt (int index, Control child)
+ {
+ throw GetNoChildrenException ();
+ }
+
+ public override void Clear ()
+ {
+ throw GetNoChildrenException ();
+ }
+
+ public override void Remove (Control value)
+ {
+ throw GetNoChildrenException ();
+ }
+
+ public override void RemoveAt (int index)
+ {
+ throw GetNoChildrenException ();
+ }
+
+ InvalidOperationException GetNoChildrenException ()
+ {
+ 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.");
+ }
+ }
+
ITemplate _contentTemplate;
Control _contentTemplateContainer;
UpdatePanelUpdateMode _updateMode = UpdatePanelUpdateMode.Always;
bool _childrenAsTriggers = true;
- bool _requiresUpdate = false;
+ bool _requiresUpdate;
+ bool _inPartialRendering;
UpdatePanelTriggerCollection _triggers;
UpdatePanelRenderMode _renderMode = UpdatePanelRenderMode.Block;
ScriptManager _scriptManager;
+ Control cachedParent;
+ UpdatePanel parentPanel;
+ bool parentPanelChecked;
+
+ UpdatePanel ParentPanel {
+ get {
+ Control parent = Parent;
+ if (cachedParent == parent && parentPanelChecked)
+ return parentPanel;
+ cachedParent = parent;
+ parentPanel = FindParentPanel (parent);
+
+ return parentPanel;
+ }
+ }
+
[Category ("Behavior")]
[DefaultValue (true)]
public bool ChildrenAsTriggers {
get {
if (_contentTemplateContainer == null) {
_contentTemplateContainer = CreateContentTemplateContainer ();
- Controls.Add (_contentTemplateContainer);
+ ((SingleChildControlCollection) Controls).AddInternal (_contentTemplateContainer);
}
return _contentTemplateContainer;
}
}
public override sealed ControlCollection Controls {
- get {
- return base.Controls;
- }
+ get { return base.Controls; }
}
[Browsable (false)]
public bool IsInPartialRendering {
- get {
- return ScriptManager.IsInPartialRendering;
- }
+ get { return _inPartialRendering; }
}
[Category ("Layout")]
protected internal virtual bool RequiresUpdate {
get {
- return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate;
+ return UpdateMode == UpdatePanelUpdateMode.Always || _requiresUpdate || AnyTriggersFired ();
}
}
}
}
+ bool AnyTriggersFired ()
+ {
+ if (_triggers == null || _triggers.Count == 0)
+ return false;
+
+ foreach (UpdatePanelTrigger trigger in _triggers)
+ if (trigger.HasTriggered ())
+ return true;
+
+ return false;
+ }
+
[Category ("Behavior")]
[DefaultValueAttribute (UpdatePanelUpdateMode.Always)]
public UpdatePanelUpdateMode UpdateMode {
}
}
- protected virtual Control CreateContentTemplateContainer () {
+ // Used by nested panels (see bug #542441)
+ ScriptManager.AlternativeHtmlTextWriter RenderChildrenWriter { get; set; }
+
+ protected virtual Control CreateContentTemplateContainer ()
+ {
return new Control ();
}
- [MonoTODO ()]
- protected override sealed ControlCollection CreateControlCollection () {
- // TODO: Because this method is protected and sealed, it is visible to classes that inherit
- // from the UpdatePanel class, but it cannot be overridden. This method overrides
- // the base implementation to return a specialized ControlCollection object that throws
- // an InvalidOperationException when the Add(Control), AddAt(Int32, Control), Clear(),
- // Remove(Control), or RemoveAt(Int32) method of the ControlCollection class is invoked.
- // To change the content of the UpdatePanel control, modify the child controls of
- // the ContentTemplateContainer property.
-
- return base.CreateControlCollection ();
+ protected override sealed ControlCollection CreateControlCollection ()
+ {
+ return new SingleChildControlCollection (this);
}
- protected internal virtual void Initialize () {
- if (_triggers != null) {
- for (int i = 0; i < _triggers.Count; i++) {
- _triggers [i].Initialize ();
- }
- }
+ protected internal virtual void Initialize ()
+ {
+ if (_triggers == null || _triggers.Count == 0 || !ScriptManager.SupportsPartialRendering)
+ return;
+
+ _triggers.Initialize ();
}
protected internal override void OnInit (EventArgs e) {
base.OnInit (e);
ScriptManager.RegisterUpdatePanel (this);
-
+ if (ParentPanel != null)
+ ScriptManager.RegisterChildUpdatePanel (this);
+
if (ContentTemplate != null)
ContentTemplate.InstantiateIn (ContentTemplateContainer);
}
writer.RenderEndTag ();
}
- protected internal override void RenderChildren (HtmlTextWriter writer) {
- if (ScriptManager.IsInAsyncPostBack){
- if (RequiresUpdate && !ScriptManager.IsInPartialRendering) {
- ScriptManager.IsInPartialRendering = true;
- HtmlTextWriter responseOutput = ((ScriptManager.AlternativeHtmlTextWriter) writer).ResponseOutput;
+ UpdatePanel FindParentPanel (Control parent)
+ {
+ parentPanelChecked = true;
+ while (parent != null) {
+ UpdatePanel panel = parent as UpdatePanel;
+ if (panel != null)
+ return panel;
+
+ parent = parent.Parent;
+ }
+
+ return null;
+ }
+
+ protected internal override void RenderChildren (HtmlTextWriter writer)
+ {
+ RenderChildrenWriter = null;
+
+ if (IsInPartialRendering) {
+ ScriptManager.AlternativeHtmlTextWriter altWriter = writer as ScriptManager.AlternativeHtmlTextWriter;
+ if (altWriter == null)
+ altWriter = writer.InnerWriter as ScriptManager.AlternativeHtmlTextWriter;
+
+ if (altWriter == null) {
+ UpdatePanel parentPanel = ParentPanel;
+ if (parentPanel != null)
+ altWriter = parentPanel.RenderChildrenWriter;
+ }
+
+ if (altWriter == null)
+ throw new InvalidOperationException ("Internal error. Invalid writer object.");
+
+ // Used by nested panels (see bug #542441)
+ RenderChildrenWriter = altWriter;
+ try {
+ HtmlTextWriter responseOutput = altWriter.ResponseOutput;
StringBuilder sb = new StringBuilder ();
HtmlTextWriter w = new HtmlTextWriter (new StringWriter (sb));
base.RenderChildren (w);
w.Flush ();
-
- ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
-
- ScriptManager.IsInPartialRendering = false;
- }
- else {
- if (ScriptManager.IsInPartialRendering)
- ScriptManager.RegisterChildUpdatePanel (this);
- base.RenderChildren (writer);
+ UpdatePanel parent = ParentPanel;
+ if (parent != null && parent.ChildrenAsTriggers)
+ writer.Write (sb.ToString ());
+ else
+ ScriptManager.WriteCallbackPanel (responseOutput, this, sb);
+ } finally {
+ RenderChildrenWriter = null;
}
- }
- else
+ } else
base.RenderChildren (writer);
}
- public void Update () {
+ internal void SetInPartialRendering (bool setting)
+ {
+ _inPartialRendering = setting;
+ }
+
+ public void Update ()
+ {
+ if (UpdateMode == UpdatePanelUpdateMode.Always)
+ throw new InvalidOperationException ("The Update method can only be called on UpdatePanel with ID '" + ID + "' when UpdateMode is set to Conditional.");
+
_requiresUpdate = true;
}
}