【问题标题】:ASP.Net Container Control DesignerASP.Net 容器控制设计器
【发布时间】:2011-05-12 17:57:31
【问题描述】:

我放弃了……在试图弄清楚我错过了什么之后,我放弃了。我无法弄清楚如何让我的简单容器控件正确显示在设计器中。下面是自定义控件的基本标记:

<div>
    <div>Title</div>
    <div>
        <!-- ASP.Net child controls -->
    </div>
</div>

这是它在运行时的样子(标题和子控件是 GridView):

下面是基本容器控件的简单代码:

namespace Shoe.Controls
{
    //[Designer(typeof(ApplicationWindowDesigner))]
    //[ParseChildren(false)]
    //[PersistChildren(true)]
    [ToolboxData("<{0}:ApplicationWindow runat=\"server\"></{0}:ApplicationWindow>")]
    public class ApplicationWindow : System.Web.UI.WebControls.Panel
    {
        #region Designer Properties
        [Category("Appearance")]
        [DefaultValue("Application")]
        [Description("Title that will appear at the top of the Window.")]
        [Browsable(true)]
        /*
        public string Title
        {
            get{return (ViewState["ApplicationWindowTitle"] == null)? 
                string.Empty : 
                (string)ViewState["ApplicationWindowTitle"];}

            set{ViewState["ApplicationWindowTitle"] = value;}
        }
        */
        public string Title {get; set;}

        #endregion
        #region Rending Methods

        /*
        protected override void Render(HtmlTextWriter writer)
        {
            this.EnsureChildControls();

            writer.Write("<div class=\""+CssClass+"\" style=\"width: "+Width+"; height: "+Height+";\"><div>"+Title+"</div><div>");
            RenderChildren(writer);
            writer.Write("</div></div>");
        }
        */

        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            writer.Write("<div class=\""+CssClass+"\" style=\"width: "+Width+"; height: "+Height+";\"><div>"+Title+"</div><div>");
            //base.RenderBeginTag(writer);
        }

        public override void RenderEndTag(HtmlTextWriter writer)
        {
            //base.RenderEndTag(writer);
            writer.Write("</div></div>");
        }
        #endregion
    }
}

正如您在上面看到的代码,它目前基于面板控件。但是,我也尝试使用 WebControl 作为基类,然后提供我自己的设计器,如下所示:

namespace Shoe.Controls
{
    public class ApplicationWindowDesigner : ContainerControlDesigner
    //public class ApplicationWindowDesigner : ControlDesigner
    {
        /*
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);

            SetViewFlags(ViewFlags.DesignTimeHtmlRequiresLoadComplete, true);
        }

        public override string GetDesignTimeHtml()
        {
            //return base.GetDesignTimeHtml();

            StringBuilder   sb  = new StringBuilder();
            TextWriter      s   = new StringWriter(sb);
            HtmlTextWriter  h   = new HtmlTextWriter(s);

            ApplicationWindow app_wnd = (ApplicationWindow)this.Component;

            app_wnd.RenderControl(h);

            h.Dispose();
            s.Dispose();

            return sb.ToString();
        }
        */
        /*
        public override string GetDesignTimeHtml(DesignerRegionCollection regions)
        {
            //return base.GetDesignTimeHtml(regions);
            ApplicationWindow app_wnd = (ApplicationWindow)this.Component;

            /
            return GetDesignTimeHtml();
        }
        */
    }
}

如您所见,我尝试使用 ControlDesigner 作为基类,使用 ContainerControlDesigner 作为基类。当我使用 ControlDesigner 时,我让设计器正确呈现我的标题栏和 div;但是它不会呈现子控件(GridView)。如果我使用 ContainerControlDesigner,它会呈现子控件,但不会呈现标题栏和 div。我想不出一个神奇的组合,它会给我一个设计器来渲染我的周围框架和子控件。

下面是使用 Panel 作为控件的基类、没有设计器和 Begin/End 标记方法时在设计器中的样子:

这也是当我使用 WebControl 作为控件的基类并使用基于 ContainerControlDesigner 的设计器时的样子(子控件,但我的标题栏和 div 不见了)。

我错过了什么?我找到了几个 ContainerControlDesigner 的例子,但没有一个像我这样真正为周围的控件添加任何东西。

【问题讨论】:

  • 我故意将注释掉的代码留在原处,以展示我尝试过的一些不同的东西。

标签: asp.net custom-controls containers designer design-time


【解决方案1】:

你在正确的轨道上......我做了类似的事情来制作圆形面板。只需放入面板并让渲染创建周围的 div 就变得非常容易。我可以将子控件放入其中,并且它们可以正确呈现。简单地包装基本渲染方法。

Web 控制(工作示例)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace MyExample
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:myPanel runat=server></{0}:bPanel>")]
    [Designer(typeof(MyPanelDesigner))]
    public class MyPanel : Panel
    {
        #region Property


        private string _Title = "No Title Set";
        public string Title
        {
            get { return _Title; }
            set { _Title = value; }
        }

        #endregion

        protected override void RenderChildren(HtmlTextWriter writer)
        {

            writer.Write(String.Format("<div><div>{0}</div></div>", this.Title));
            base.RenderChildren(writer);
            writer.Write("</div></div>");
        }

    }


    public class MyPanelDesigner : PanelContainerDesigner
    {
        public override string GetDesignTimeHtml(System.Web.UI.Design.DesignerRegionCollection regions)
        {
            // Read Property off control
            MyPanel c = (MyPanel)Component;
            string sTitle = c.Title;

            // Render design markup
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("<div><div>{0}</div></div>", sTitle);
            sb.Append(base.GetDesignTimeHtml(regions));
            sb.AppendFormat("</div></div>");
            return sb.ToString();
        }
    }

}

【讨论】:

  • 做到了。我真正缺少的是设计器中的 base.GetDesignTimeHtml 调用。我尝试只调用基类并尝试用我自己的代码替换该方法(如您在我的原始帖子中所见),我从未想过将两者混合。现在似乎很明显......
猜你喜欢
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 2011-07-13
  • 2013-10-26
  • 1970-01-01
  • 2018-09-29
相关资源
最近更新 更多