#region License
/*
* Copyright 2002-2004 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
using System;
using System.Reflection;
using System.Web.UI;
using Common.Logging;
namespace Spring.Web.UI.Controls{
/// <summary>
/// Represents Content control that can be used to populate or override placeholders
/// anywhere within the page.
/// </summary>
/// <remarks>
/// <para>
/// Any content defined within this control will override default content
/// in the matching control specified by <see cref="ContentPlaceHolderID"/> anywhere
/// within the page.
/// </para>
/// <para>
/// In contrast to <see cref="Content"/> control, ContentReplacer can replace the content of
/// any control within the current page - it is not limited to replacing ContentPlaceholders on master pages.
/// </para>
/// <para>
/// This technique is useful if you want to group e.g. rendering navigation elements on 1 ascx control, but your
/// design requires navigation elements to be distributed across different places within the HTML code.
/// </para>
/// </remarks>
/// <author>Erich Eichinger</author>
public class ContentReplacer : Control
{
private static readonly ILog log = LogManager.GetLogger(typeof(ContentReplacer));
private string contentPlaceHolderID;
/// <summary>
/// Specifies the unique id of the control, who's content is to be replaced.
/// </summary>
public string ContentPlaceHolderID
{
get { return contentPlaceHolderID; }
set { contentPlaceHolderID = value; }
}
/// <summary>
/// Overriden to correctly redirect rendermethod calls.
/// </summary>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// if our container is not visible, don't replace placeholder's content
if (!Visible) return;
//log.Debug(string.Format("OnPreRender Content['{0}']", this.contentPlaceHolderID));
#if NET_1_1
Control ctlRoot = this.Page;
if (ctlRoot is Spring.Web.UI.Page)
{
MasterPage masterPage = ((Spring.Web.UI.Page) ctlRoot).Master;
if (masterPage != null)
{
ctlRoot = masterPage;
}
}
#else
Control ctlRoot = (this.Page.Master != null) ? (Control)this.Page.Master : (Control)this.Page;
#endif
Control ctl = ctlRoot.FindControl(this.contentPlaceHolderID);
if (ctl != null)
{
log.Debug(string.Format("OnPreRender Content['{0}'] found placeholder - replacing RenderMethod",this.contentPlaceHolderID));
RenderMethod myRenderMethod = GetRenderMethod();
//log.Debug(string.Format("OnPreRender Content['{0}'] renderMethod found={1}", this.contentPlaceHolderID,(myRenderMethod != null ? "true" : "false")));
// prevent content control from rendering itself
this.SetRenderMethodDelegate(new RenderMethod(RenderNothing));
if (myRenderMethod == null)
{
myRenderMethod = new RenderMethod(RenderChildControls);
}
// instead replace placeholder's rendermethod to render this control's content
ctl.SetRenderMethodDelegate(myRenderMethod);
}
else
{
throw new ArgumentException(string.Format("No ContentPlaceHolder with id '{0}' defined on this page.", this.contentPlaceHolderID));
}
}
/// <summary>
/// Renders child controls
/// </summary>
private void RenderChildControls(HtmlTextWriter output, Control container)
{
if (this.HasControls())
{
foreach (Control ctl in this.Controls)
{
ctl.RenderControl(output);
}
}
}
/// <summary>
/// Render nothing.
/// </summary>
private void RenderNothing(HtmlTextWriter output, Control container)
{
// do nothing
}
#if NET_2_0
private static readonly PropertyInfo piRareFieldsEnsured =
typeof(Control).GetProperty("RareFieldsEnsured", BindingFlags.NonPublic | BindingFlags.Instance);
private static readonly FieldInfo fiRenderMethod =
typeof(Control).GetNestedType("ControlRareFields",BindingFlags.NonPublic).GetField("RenderMethod");
private RenderMethod GetRenderMethod()
{
object o = piRareFieldsEnsured.GetValue(this, null);
RenderMethod myRenderMethod = (RenderMethod) fiRenderMethod.GetValue(o);
return myRenderMethod;
}
#else
private static readonly FieldInfo fiRenderMethod =
typeof(Control).GetField("_renderMethod", BindingFlags.NonPublic | BindingFlags.Instance);
private RenderMethod GetRenderMethod()
{
RenderMethod myRenderMethod = (RenderMethod)fiRenderMethod.GetValue(this);
return myRenderMethod;
}
#endif
}
}
|