File: UI\TemplateBuilder.cs
Project: ndp\fx\src\xsp\system\Web\System.Web.csproj (System.Web)
//------------------------------------------------------------------------------
// <copyright file="TemplateBuilder.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
 * Classes related to templated control support
 *
 * Copyright (c) 1999 Microsoft Corporation
 */
namespace System.Web.UI {
    using System;
    using System.Collections;
    using System.Reflection;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Security.Permissions;
    /*
     * This class defines the TemplateAttribute attribute that can be placed on
     * properties of type ITemplate.  It allows the parser to strongly type the
     * container, which makes it easier to write render code in a template
     */
 
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    [AttributeUsage(AttributeTargets.Property)]
    public sealed class TemplateContainerAttribute : Attribute {
        private Type _containerType;
 
        private BindingDirection _bindingDirection;
 
 
        /// <devdoc>
        /// <para>Whether the template supports two-way binding.</para>
        /// </devdoc>
        public BindingDirection BindingDirection {
            get {
                return _bindingDirection;
            }
        }
 
 
        /// <devdoc>
        ///    <para></para>
        /// </devdoc>
        public Type ContainerType {
            get {
                return _containerType;
            }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public TemplateContainerAttribute(Type containerType) : this(containerType, BindingDirection.OneWay) {
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public TemplateContainerAttribute(Type containerType, BindingDirection bindingDirection) {
            _containerType = containerType;
            _bindingDirection = bindingDirection;
        }
    }
 
 
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    public class TemplateBuilder : ControlBuilder, ITemplate {
        internal string _tagInnerText;
 
        private bool _allowMultipleInstances;
 
        private IDesignerHost _designerHost;
 
 
        public TemplateBuilder() {
            _allowMultipleInstances = true;
        }
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        //  ID parameter name changed from ControlBuilder, so leave this to avoid a "breaking change"
        public override void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string ID, IDictionary attribs) {
            base.Init(parser, parentBuilder, type, tagName, ID, attribs);
 
            if (InPageTheme && ParentBuilder != null && ParentBuilder.IsControlSkin) {
                ((PageThemeParser)Parser).CurrentSkinBuilder = parentBuilder;
            }
        }
 
        public override void CloseControl() {
            base.CloseControl();
 
            if (InPageTheme && ParentBuilder != null && ParentBuilder.IsControlSkin) {
                ((PageThemeParser)Parser).CurrentSkinBuilder = null;
            }
        }
 
        internal bool AllowMultipleInstances {
            get { return _allowMultipleInstances; }
            set { _allowMultipleInstances = value; }
        }
 
        // This code is only executed when used from the designer
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public override object BuildObject() {
            return this;
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public override bool NeedsTagInnerText() {
            // We want SetTagInnerText() to be called if we're running in the
            // designer.
            return InDesigner;
        }
 
        internal void SetDesignerHost(IDesignerHost designerHost) {
            _designerHost = designerHost;
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public override void SetTagInnerText(string text) {
            // Save the inner text of the template tag
            _tagInnerText = text;
        }
 
        /*
         * ITemplate implementation
         * This implementation of ITemplate is only used in the designer
         */
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public virtual void InstantiateIn(Control container) {
 
            IServiceProvider builderServiceProvider = null;
 
            // Use the designer host to get one at designtime as the service provider
            if (_designerHost != null) {
                builderServiceProvider = _designerHost;
            }
            else if (!IsNoCompile) {
                // Otherwise, create a ServiceContainer and try using the container as the service provider
                ServiceContainer serviceContainer = new ServiceContainer();
                if (container is IThemeResolutionService) {
                    serviceContainer.AddService(typeof(IThemeResolutionService), (IThemeResolutionService)container);
                }
 
                if (container is IFilterResolutionService) {
                    serviceContainer.AddService(typeof(IFilterResolutionService), (IFilterResolutionService)container);
                }
                builderServiceProvider = serviceContainer;
            }
 
            HttpContext context = null;
            TemplateControl savedTemplateControl = null;
 
            TemplateControl templateControl = container as TemplateControl;
 
            if (templateControl != null) {
                context = HttpContext.Current;
                if (context != null)
                    savedTemplateControl = context.TemplateControl;
            }
 
            try {
                if (!IsNoCompile)
                    SetServiceProvider(builderServiceProvider);
 
                if (context != null) {
                    context.TemplateControl = templateControl;
                }
 
                BuildChildren(container);
            }
            finally {
                if (!IsNoCompile)
                    SetServiceProvider(null);
 
                // Restore the previous template control
                if (context != null)
                    context.TemplateControl = savedTemplateControl;
            }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public virtual string Text {
            get { return _tagInnerText; }
            set { _tagInnerText = value; }
        }
    }
 
    // Delegates used for the compiled template
 
    /// <internalonly/>
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    public delegate void BuildTemplateMethod(Control control);
 
    /*
     * This class is the ITemplate implementation that is called from the
     * generated page class code.  It just passes the Initialize call on to a
     * delegate.
     */
 
    /// <internalonly/>
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    public sealed class CompiledTemplateBuilder : ITemplate {
        private BuildTemplateMethod _buildTemplateMethod;
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public CompiledTemplateBuilder(BuildTemplateMethod buildTemplateMethod) {
            _buildTemplateMethod = buildTemplateMethod;
        }
 
        // ITemplate::InstantiateIn
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void InstantiateIn(Control container) {
            _buildTemplateMethod(container);
        }
    }
}