第二章 .Net 控件开发(WebForm) 开发自定义复合控件(2) 重写属性和方法

1、 上一章节讲到了创建容器的子控件,最后用一个图来理解,这章节继续接着上节来着,继续按照创建复合容器的控件步骤来。

2、 第七步,为容器控件创建样式。ApplyContainerStyles方法为每个控件调用ApplyContainerStyle方法。

 ComContainer Ccn_LblName;
        ComContainer Ccn_TxtName;
        ComContainer Ccn_BtnShow;

        protected virtual void ApplyContainerStyles()
        {
            ApplyContainerStyle(Ccn_LblName);
            ApplyContainerStyle(Ccn_BtnShow);
        }

        private void ApplyContainerStyle(ComContainer container)
        {
            if (container.ContainerType == ContainerType.ShowButton)
            {
                container.ColumnSpan = 2;
                container.HorizontalAlign = HorizontalAlign.Center;
            }
        }

3、 第八步,将容器控件添加到复合控件,将实现AddContainer方法。

protected virtual void AddContainer(ComContainer container)
        {
            this.Controls.Add(container);
        }

4、 第九步,呈现容器控件,也实现RenderContainer方法。

protected virtual void RenderContainer(ComContainer container, HtmlTextWriter writer)
        {
            container.RenderControl(writer);
        }

5、 第十步,重写CreateChildControls方法,通过重写该方法可创建需要继承到自定义控件中的子控件。有关子控件的一个重要的需要注意的问题是:子控件是按需要创建的。不要假设子控件是在自定义控件生命周期的某个特殊阶段进行创建的。子控件可以在任何时间创建的。换句话说:可以自定义控件在生命周期的任何阶段调用CreateChildControls方法创建子控件。这是个重要的结论。结论之一是:必须在一个仅且在一个地方来创建自定义控件的子控件——CreateChildControls方法。自定义控件不能在任何其它地方创建子控件。如果在其它地方创建子控件,则无法按需要来创建。原因是Asp.Net框架通过调用CreateChildControls方法方法来完成按需要创建子控件,可以这么认为CreateChildControls方法用于创建一站式子控件,不能在其它地方创建。看代码的实现过程,子控件不会在自定义控件声明周期的特殊阶段被创建。它们是按需要来创建的。这意味这CreateChildControls方法可能会被多次调用。这样会浪费服务器资源,原因是无论是否已经创建子控件,该方法会被多次调用,为了解决这个问题在创建控件好后将ChildControlsCreated属性设置为true,这样可以避免多次被调用。

protected override void CreateChildControls()
        {
            //base.CreateChildControls();
            Controls.Clear();

            Ccn_LblName = CreateContainer(ContainerType.UserLable);
            CreateContainerChildControl(Ccn_LblName);
            AddContainer(Ccn_LblName);

            Ccn_TxtName = CreateContainer(ContainerType.UserTextBox);
            CreateContainerChildControl(Ccn_TxtName);
            AddContainer(Ccn_TxtName);

            Ccn_BtnShow = CreateContainer(ContainerType.ShowButton);
            CreateContainerChildControl(Ccn_BtnShow);
            AddContainer(Ccn_BtnShow);

            ChildControlsCreated = true;
        }

6、 第十一步,重写TagKey属性,我们用的是表格。所以要重写该属性。

protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Table;
                //return base.TagKey;
            }
        }

7、 第十二步,重写CreateControlStyle方法,既然重写TagKey我们也有必要重写该方法。

protected override Style CreateControlStyle()
        {
            return new TableStyle(ViewState);
            //return base.CreateControlStyle();
        }

8、 第十三步,公开ControlStyle属性,将最外层元素设置Table后,我们可以公开几个属性,我们这里采取的是第一章(5)里面说到的那两个属性。

public virtual int CellSpacing 
        {
            get
            {
                return ((TableStyle)ControlStyle).CellSpacing;
            }           
            set 
            { 
                ((TableStyle)ControlStyle).CellSpacing = value; 
            }          
        }   
        public virtual int CellPadding          
        {
            get
            {
                return ((TableStyle)ControlStyle).CellPadding;
            }
            set 
            { 
                ((TableStyle)ControlStyle).CellPadding = value; 
            }
        }

9、 第十四步,重写RenderContent方法。按需求布局

protected override void RenderContents(HtmlTextWriter writer)
        {
            //base.RenderContents(writer);
            ApplyContainerStyles();
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            RenderContainer(Ccn_LblName, writer);
            RenderContainer(Ccn_TxtName, writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            RenderContainer(Ccn_BtnShow, writer);
            writer.RenderEndTag();

        }

10、 和上节一样,我现在用个流程图来再说明下。(1)、(2)、(3)就是实现了CreateChildControls的过程;(4)就是将子控件集成到ComTestControl中,通过RenderContents方法实现这里先要理解是如何集成的。

【1】 WebControls类所实现的RenderContent方法调用基类的Render方法

        protected internal virtual void RenderContents(HtmlTextWriter writer)
        {
            base.Render(writer);
        }

【2】 Render方法调用了Control基类的RenderChilder方法

        protected internal virtual void Render(HtmlTextWriter writer)
        {
            base.RenderChildren(writer);
        }

【3】 RenderChildren方法按将子控件添加Controls集合中的顺序,调用RenderControl方法

        protected internal virtual void RenderChildren(HtmlTextWriter writer)
        {
            foreach (Control ChildControl in Controls)
            {
                ChildControl.RenderControl(writer);
            }
        }

总之,RenderContents方法的默认实现是按照使用CreateChildControls方法将子控件添加到Contros集合顺序,来完成子控件的集合。如果不重写RenderContents方法大家看下,控件是简单的罗列到页面中。


CreateChildControls方法用于创建个初始化需要继承到自定义控件内的子控件;
RenderContents方法将子控件集成到自定义控件中。

 

代码下载地址:点击下载

本博客内容有些来源于网络或书籍如果侵害到你的权益,请及时联系我(hch458458@vip.qq.com)
版权归nethch所有,转载请注明出处!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值