65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ASP.Net 用户控件设计器中隐藏内容

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2014年5月14日

CPOL

2分钟阅读

viewsIcon

10556

如何修复在 Visual Studio 用户控件设计器中隐藏控件的问题

引言

Visual Studio 有一个很棒的设计器......但不幸的是,它有一些限制。 其中一个特别令人恼火:无论您对“DesignMode”做什么,用户控件总是会被渲染。

由于这个问题自 2008 年以来一直存在,并且在四处搜索一番后,我仍然没有找到解决方案,所以我决定解决它。

背景

有时您的用户控件中会有很多阻塞。 例如,如果您有一个漂亮的弹出面板来执行您的登录、注销、注册等操作,并且您将其放在您的母版页中,您最终会在每个页面上破坏您的设计器,或者花费大量时间编写服务器控件。

这实际上是 Visual Studio 本身的功能:为了方便开发人员,如果您从 UserControl 派生类,它们只需渲染子控件。 此限制仅适用于用户控件,服务器控件没有此限制。

但是,我们不希望这样,所以我们需要的是一个懒惰的解决方案,不需要(重新)编写用户控件代码。

这给了我一个想法:如果我们只是将所有想要在设计时隐藏的内容包装在一个小型服务器控件中,我们可以隐藏我们想要的任何内容,包括用户控件内容。

构建服务器控件

我们的服务器控件非常简单:如果我们在网站上运行,它需要能够渲染其内容,如果在设计时,则隐藏内容。

可以通过重写 RenderControl 方法来隐藏设计时内容。 如果我们不输出任何内容,设计器会介入并给我们一个丑陋的消息,告诉我们那里有一个控件 - 这就是我渲染一个空格的原因 :-)

所以这是(全部)代码

    public class ContentTemplateContainer : Control, INamingContainer
    {
    }

    [ToolboxData("<{0}:HiddenControlContainer runat='server'><ContentTemplate></ContentTemplate></{0}:HiddenControlContainer>")]
    [ParseChildren(true), PersistChildren(false)]
    public class HiddenControlContainer : WebControl
    {
        [TemplateContainer(typeof(ContentTemplateContainer))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateInstance(TemplateInstance.Single)]
        public ITemplate ContentTemplate { get; set; }

        protected override void OnInit(EventArgs e)
        {
            if (!DesignMode)
            {
                if (ContentTemplate != null)
                {
                    var container = new ContentTemplateContainer();
                    this.Controls.Add(container);
                    ContentTemplate.InstantiateIn(container);
                }
            }
            base.OnInit(e);
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            if (!DesignMode)
            {
                base.RenderControl(writer);
            }
            else
            {
                writer.Write(" ");
            }
        }
    } 

这些属性确保设计器也会为模板生成代码,这基本上意味着您可以简单地将它包装在您的控件周围而不会破坏它。 唯一会改变的是客户端 ID,因为内容包装在 INamingContainer 中。

使用控件

使用该控件很容易:将您的用户控件内容(或您想要隐藏的任何内容)包装在内容模板中,就完成了。

<pz:HiddenControlContainer ID="loginContent" runat="server">
<ContentTemplate>
    <!-- Original user control contents -->
</ContentTemplate>
</pz:HiddenControlContainer> 

结果呢?

让我们在设计器中再次渲染用户控件

漂亮和白色,正是我们想要的。 是的,这看起来很棒 :-)

历史

2014 年 5 月 14 日 - 初始文章

© . All rights reserved.