#region License
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Spring.Context;
using Spring.Context.Support;
using Spring.Util;
using Spring.Web.Support;
#endregion
namespace Spring.Web.UI.Controls{
/// <summary>
/// This panel provides the same features as <see cref="System.Web.UI.WebControls.Panel"/>, but provides additional means with regards to Spring.
/// </summary>
/// <remarks>
/// In some cases, automatic dependency injection can cause performance problems. In this case,you can use a Panel for finer-grained control
/// over which controls are to be injected or not.
/// </remarks>
/// <author>Erich Eichinger</author>
[PersistChildren(true),
ToolboxData("<{0}:Panel runat=\"server\" Width=\"125px\" Height=\"50px\"> </{0}:Panel>"),
ParseChildren(false),
#if NET_1_1
Designer("System.Web.UI.Design.WebControls.PanelDesigner, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
#else
Designer("System.Web.UI.Design.WebControls.PanelContainerDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
#endif
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class Panel : System.Web.UI.WebControls.Panel, ISupportsWebDependencyInjection
{
// this helper class intercepts the first call to the child controls
// collection from within InitRecursive().
// InitRecursive() is called right after the control has been added to it's parent's children.
private class InitRecursiveInterceptingControlsCollection : ControlCollection
{
private bool _passedInitRecursiveCheck = false;
public InitRecursiveInterceptingControlsCollection(Control owner) : base(owner)
{
}
public override Control this[int index]
{
get
{
// the following check relies on the fact, that ControlCollection is set readonly
// right before InitRecursive() is called on each child control
if (!_passedInitRecursiveCheck
&& this.IsReadOnly)
{
_passedInitRecursiveCheck = true;
((Panel)this.Owner).OnPreInitRecursive(EventArgs.Empty);
}
return base[index];
}
}
}
private bool _suppressDependencyInjection;
private bool _renderContainerTag;
private string _visibleConditionExpression;
/// <summary>
/// An optional SpEL expression to control this Panel's <see cref="Control.Visible"/> state.
/// </summary>
/// <remarks>
/// This panel instance is the context for evaluating the given expression. If no expression is specified, visibility behavior
/// reverts to standard behavior.
/// </remarks>
public string VisibleIf
{
get { return _visibleConditionExpression; }
set { _visibleConditionExpression = value; }
}
/// <summary>
/// This flag controls, whether DI on child controls will be done or not
/// </summary>
/// <remarks>By default, DI will be done</remarks>
public bool SuppressDependencyInjection
{
get { return _suppressDependencyInjection; }
set { _suppressDependencyInjection = value; }
}
/// <summary>
/// This flag controls, whether this Panel's tag will be rendered.
/// </summary>
public bool RenderContainerTag
{
get { return _renderContainerTag; }
set { _renderContainerTag = value; }
}
/// <summary>
/// Overridden to set <see cref="Control.Visible"/> according to <see cref="VisibleIf"/> if necessary.
/// </summary>
protected override void OnPreRender( EventArgs e )
{
this.Visible = (_visibleConditionExpression != null)
? Spring.Expressions.ExpressionEvaluator.GetValue(this, _visibleConditionExpression).Equals(true)
: this.Visible;
base.OnPreRender( e );
}
///<summary>
///Renders the HTML opening tag of the <see cref="Panel"></see> control to the specified writer.
///</summary>
///<param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output stream to render HTML content on the client.</param>
public override void RenderBeginTag( HtmlTextWriter writer )
{
if (this.RenderContainerTag)
{
base.RenderBeginTag( writer );
}
}
///<summary>
///Renders the HTML closing tag of the <see cref="Panel"></see> control to the specified writer.
///</summary>
///<param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output stream to render HTML content on the client.</param>
public override void RenderEndTag( HtmlTextWriter writer )
{
if (this.RenderContainerTag)
{
base.RenderEndTag( writer );
}
}
/// <summary>
/// This method is invoked right before InitRecursive() is called for this Panel and
/// ensures, that dependencies get injected on child controls before their Init event is raised.
/// </summary>
protected virtual void OnPreInitRecursive(EventArgs e)
{
if (!_suppressDependencyInjection
&& _defaultApplicationContext == null)
{
// obtain appContext of the closed parent template (.ascx/.aspx) control
IApplicationContext appCtx = WebApplicationContext.GetContext(this.TemplateSourceDirectory.TrimEnd('/') + "/");
// NOTE: _defaultApplicationContext will be set during DI!
WebDependencyInjectionUtils.InjectDependenciesRecursive(appCtx, this);
}
}
/// <summary>
/// Expose the context of this panel for medium trust safe access in e.g. <see cref="VisibleIf"/>.
/// </summary>
public new virtual HttpContext Context
{
get { return base.Context; }
}
#region Dependency Injection Support
private IApplicationContext _defaultApplicationContext;
/// <summary>
/// Sets / Gets the ApplicationContext instance used to configure this control
/// </summary>
IApplicationContext ISupportsWebDependencyInjection.DefaultApplicationContext
{
get { return _defaultApplicationContext; }
set { _defaultApplicationContext = value; }
}
/// <summary>
/// Injects dependencies into control before adding it.
/// </summary>
protected override void AddedControl(Control control, int index)
{
if (!_suppressDependencyInjection
&& _defaultApplicationContext != null)
{
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
}
base.AddedControl(control, index);
}
/// <summary>
/// Overridden to automatically aquire a reference to
/// root application context to use for DI.
/// </summary>
protected override ControlCollection CreateControlCollection()
{
// set root application context to signal, that we care
// for our children ourselves
if (_suppressDependencyInjection)
{
_defaultApplicationContext = WebApplicationContext.GetRootContext();
return base.CreateControlCollection();
}
else
{
return new InitRecursiveInterceptingControlsCollection(this);
}
}
#endregion Dependency Injection Support
}
}
|