/// <include file='doc\TemplatedControlDesigner.uex' path='docs/doc[@for="TemplatedControlDesigner.SaveActiveTemplateEditingFrame"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Saves the active template frame.
        ///    </para>
        /// </devdoc>
        protected void SaveActiveTemplateEditingFrame()
        {
            Debug.Assert(InTemplateMode, "SaveActiveTemplate should be called only when in template mode");
            Debug.Assert(ActiveTemplateEditingFrame != null, "An active template frame should be present in SaveActiveTemplate");

            ActiveTemplateEditingFrame.Save();
        }
        /// <include file='doc\TemplatedControlDesigner.uex' path='docs/doc[@for="TemplatedControlDesigner.ExitTemplateMode"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Closes the currently active template editing frame after saving any relevant changes.
        ///    </para>
        /// </devdoc>
        public void ExitTemplateMode(bool fSwitchingTemplates, bool fNested, bool fSave)
        {
            Debug.Assert(ActiveTemplateEditingFrame != null, "Invalid current template frame!");

            try {
                IWebFormsDocumentService wfServices = (IWebFormsDocumentService)GetService(typeof(IWebFormsDocumentService));
                Debug.Assert(wfServices != null, "Did not get IWebFormsDocumentService");

                // First let the inner/nested designers handle exiting of their template mode.
                // Note: This has to be done inside-out in order to ensure that the changes
                // made in a particular template are saved before its immediate outer level
                // control designer saves its children.
                ExitNestedTemplates(fSave);

                // Save the current contents of all the templates within the active frame, and
                // close the frame by removing it from the tree.
                ActiveTemplateEditingFrame.Close(fSave);

                // Reset the pointer to the active template frame.
                // NOTE: Do not call activeTemplateFrame.Dispose here - we're in the process of exiting template mode
                //       and calling Dispose will attempt to exit template mode again. Calling dispose would also
                //       throw away the cached html tree, which we want to hang on for perf reasons.
                activeTemplateFrame = null;

                if (!fSwitchingTemplates)
                {
                    // No longer in template editing mode.
                    // This will fire the OnTemplateModeChanged notification
                    SetTemplateMode(false, fSwitchingTemplates);

                    // When not switching from one template frame to another and it is the
                    // outer most designer being switched out of template editing, then
                    // update its design-time html:

                    if (!fNested)
                    {
                        UpdateDesignTimeHtml();

                        // Invalidate the type descriptor so that proper filtering of properties
                        // is done when exiting template mode.
                        TypeDescriptor.Refresh(Component);

                        if (wfServices != null)
                        {
                            wfServices.UpdateSelection();
                        }
                    }
                }
            }
            catch (Exception) {
            }
        }
        /// <include file='doc\TemplatedControlDesigner.uex' path='docs/doc[@for="TemplatedControlDesigner.OnComponentChanged"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Delegate to handle the component changed event.
        ///    </para>
        /// </devdoc>
        public override void OnComponentChanged(object sender, ComponentChangedEventArgs ce)
        {
            // Call the base class implementation first.
            base.OnComponentChanged(sender, ce);

            if (InTemplateMode)
            {
                if ((ce.Member != null) && (ce.NewValue != null) && ce.Member.Name.Equals("ID"))
                {
                    // If the ID property changes when in template mode, update it in the
                    // active template editing frame.

                    Debug.Assert(ActiveTemplateEditingFrame != null, "Valid template frame should be present when in template mode");
                    ActiveTemplateEditingFrame.UpdateControlName(ce.NewValue.ToString());
                }
            }
        }
        /// <include file='doc\TemplatedControlDesigner.uex' path='docs/doc[@for="TemplatedControlDesigner.EnterTemplateMode"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Opens a particular template frame object for editing in the designer.
        ///    </para>
        /// </devdoc>
        public void EnterTemplateMode(ITemplateEditingFrame newTemplateEditingFrame)
        {
            Debug.Assert(newTemplateEditingFrame != null, "New template frame passed in is null!");

            // Return immediately when trying to open (again) the currently active template frame.
            if (ActiveTemplateEditingFrame == newTemplateEditingFrame)
            {
                return;
            }

            Debug.Assert((Behavior == null) || (Behavior is IControlDesignerBehavior), "Invalid element behavior!");
            IControlDesignerBehavior behavior = (IControlDesignerBehavior)Behavior;

            IWebFormsDocumentService wfServices = (IWebFormsDocumentService)GetService(typeof(IWebFormsDocumentService));

            Debug.Assert(wfServices != null, "Did not get IWebFormsDocumentService");

            try {
                bool switchingTemplates = false;
                if (InTemplateMode)
                {
                    // This is the case of switching from template frame to another.
                    switchingTemplates = true;
                    ExitTemplateMode(switchingTemplates, /*fNested*/ false, /*fSave*/ true);
                }
                else
                {
                    // Clear the design time HTML when entering template mode from read-only/preview mode.
                    if (behavior != null)
                    {
                        behavior.DesignTimeHtml = String.Empty;
                    }
                }

                // Hold onto the new template frame as the currently active template frame.
                this.activeTemplateFrame = newTemplateEditingFrame;

                // The designer is now in template editing mode.
                if (templateMode == false)
                {
                    SetTemplateMode(/*templateMode*/ true, switchingTemplates);
                }

                // Open the new template frame and make it visible.
                ActiveTemplateEditingFrame.Open();

                // Mark the designer as dirty when in template mode.
                IsDirty = true;

                // Invalidate the type descriptor so that proper filtering of properties
                // is done when entering template mode.
                TypeDescriptor.Refresh(Component);
            }
            catch (Exception) {
            }

            if (wfServices != null)
            {
                wfServices.UpdateSelection();
            }
        }