《转》http://www.pin5i.com/showtopic-11037.html

网站上的广告内容可能会因加载过慢而导致整个网页加载过慢,我们可以考虑将广告内全部放在网页最底部,等整个页面加载完毕後再采用javascript使其显示,考虑给控件一个TargetContainerID标识,控件广告内容将要被显示的容器ID,然后从控件自己所处的 开始向上查找该ID所指定的控件,(我们只向上找而没有向下找,并且没有处理某层次的子NamingContainer,所以不一定能够找到,这里没有考虑从Page对象向下递归查找主要考虑为了提高性能),如果没有找到,则考虑给用户一个事件让用户自己处理TargetContainer。

下面的自定义控件对此实现了封装:
namespace HBZ.Ads.Controls
{
    using System;
    using System.ComponentModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using HBZ.Ads;
    using System.Collections.Generic;
    using System.Text;

    [Designer( typeof( HBZ.Ads.Controls.AdRotatorDesigner ) )]
    public class AdRotator : WebControl
    {
        private Dictionary<string , Control> findControlHelperCacheList = new Dictionary<string , Control>( );
        private readonly string scriptFormat = "var {0}_target = document.getElementById(\"{0}\"); var {1}_base = document.getElementById(\"{1}\"); if ({0}_target) {{ {0}_target.innerHTML = {1}_base.innerHTML; {1}_base.innerHTML = \"\"; }}";

        private static readonly object eventObj = new object( );
        public event FindTargetContainerEventHandler FindTargetContainer
        {
            add
            {
                Events.AddHandler( eventObj , value );
            }
            remove
            {
                Events.RemoveHandler( eventObj , value );
            }
        }

        public AdRotator( )
            : base( HtmlTextWriterTag.Span )
        {
        }

        [TypeConverter( typeof( ValidatedControlConverter ) )]
        [DefaultValue( "" ) , Category( "Data" ) , Description( "广告位后期加载后显示的位置的控件ID" )]
        [IDReferenceProperty]
        public string TargetContainerID
        {
            get
            {
                return (string)this.ViewState[ "TargetContainerID" ] ?? string.Empty;
            }
            set
            {
                this.ViewState[ "TargetContainerID" ] = value;
            }

        }       


        [Bindable( true ) , Category( "Data" ) , DefaultValue( "" ) , Description( "广告位的默认内容" )]
        public string DefaultContent
        {
            get
            {
                return (string)this.ViewState[ "DefaultContent" ] ?? "广告位招租";
            }
            set
            {
                this.ViewState[ "DefaultContent" ] = value;
            }
        }
        protected override void OnPreRender( EventArgs e )
        {
            base.OnPreRender( e );

            if ( !string.IsNullOrEmpty( TargetContainerID ) )
            {
                this.Style.Add( HtmlTextWriterStyle.Display , "none" );

                ClientScriptManager cs = Page.ClientScript;
                if ( !cs.IsStartupScriptRegistered( this.ClientID ) )
                {
                    cs.RegisterStartupScript( this.GetType( ) , this.ClientID , GetLazyLoadingScript( ) , true );
                }
            }
        }

        protected virtual string GetLazyLoadingScript( )
        {
            Control target = FindControlHelper( TargetContainerID );
            if ( target == null )
            {
                throw new TargetContainerNotFoundException( );
            }

            StringBuilder sb = new StringBuilder( );
            sb.AppendFormat( scriptFormat , target.ClientID , this.ClientID );

            return sb.ToString( );
        }

        protected virtual void RenderAdvertisement( Advertisement ad , HtmlTextWriter writer )
        {
            // 广告内容
        }

        protected override void RenderContents( HtmlTextWriter writer )
        {

            // call RenderAdvertisement method
        }

        protected Control FindControlHelper( string id )
        {
            Control c = null;
            if ( findControlHelperCacheList.ContainsKey( id ) )
            {
                c = findControlHelperCacheList[ id ];
            }
            else
            {
                c = base.FindControl( id );  // 注意:我们从自己开始向上沿NamingContainer层次查找
                Control nc = NamingContainer;
                while ( ( null == c ) && ( null != nc ) )
                {
                    c = nc.FindControl( id );
                    nc = nc.NamingContainer;
                }
                if ( null == c )
                {
                    // 因为我们是从自己开始向上沿NamingContainer层次查找,而没有向下找,
                    // 并且没有找每一层NamingContainer内的其他NamingContainer,
                    // 所以这种查找有可能出现没有找到id对应的控件

                    // 当没此时有找到时,激发FindTargetContainer事件交给用户自己设定Target Container Control
                    FindTargetContainerEventArgs args = new FindTargetContainerEventArgs( id );

                    OnFindTargetContainer( args );

                    c = args.Control;

                }
                if ( null != c )
                {
                    findControlHelperCacheList[ id ] = c;
                }
            }

            return c;
        }

        protected virtual void OnFindTargetContainer( FindTargetContainerEventArgs e )
        {
            FindTargetContainerEventHandler hander = Events[ eventObj ] as FindTargetContainerEventHandler;
            if ( hander != null )
            {
                hander( this , e );
            }
        }
    }

    public delegate void FindTargetContainerEventHandler( object src , FindTargetContainerEventArgs e );

    public class FindTargetContainerEventArgs : EventArgs
    {
        private string controlID;
        private Control control;

        public FindTargetContainerEventArgs( string controlId )
        {
            controlID = controlId;
        }

        public string ControlID
        {
            get
            {
                return controlID;
            }
        }

        public Control Control
        {
            get
            {
                return control;
            }
            set
            {
                control = value;
            }
        }
    }

    public class TargetContainerNotFoundException : Exception
    {
        string exceptionMessage = string.Empty;
        public TargetContainerNotFoundException( )
            : this( "TargetContainerID所指定的控件没有找到!您或许应该处理一下FindTargetContainer事件" )
        {
        }

        public TargetContainerNotFoundException( string message )
            : base( message )
        {
            this.exceptionMessage = message;
        }
        public override string Message
        {
            get
            {
                if ( exceptionMessage != null )
                {
                    return exceptionMessage;
                }
                return base.Message;
            }
        }

    }
}
http://www.cn-web.com/cnweb/0/411/article/

看不懂的话,先看下asp.net中的NamingContainer详解
文章来源(WEB开发技术知识库):http://www.cn-web.com/cnweb/0/411/article/

posted on 2008-09-02 22:33  赛纳行星  阅读(239)  评论(0编辑  收藏  举报