NULL

坚持点,平和点...【My open asp.net control projects http://www.codeplex.com/aspnetControl/】

  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理 ::
  32 随笔 :: 1 文章 :: 926 评论 :: 39 Trackbacks
主题,解析WebControl的呈现方法!

    如果您还不了解Control的呈现过程,请点击这里http://www.cnblogs.com/wmj/archive/2008/03/17/1109072.html

    先不讲WebControl呈现方法的细节问题,大家回想一下,在重写ControlRender方法的时候,整个控件的呈现逻辑全部在一个方法中实现,控件的元素,属性,样式属性混在一起,感觉特乱!有没有更好的设计方案呢?
    能不能把呈现过程分一下层呢?比如说,把最外层元素单独放在某个方法呈现,并且她的属性和样式属性也在一个独立的方法中实现,再用一个独立的方法把控件的内容呈现出来,这样感觉是不是舒服多了?在我们想这些之前,其实MS早就替我们做好了一切,当然,MS的这种设计并不一定就是十全十美的!

按照上面的思路,并对照WebControl的方法进行讲解!
        一,用来呈现控件最外层元素的方法或者属性是怎样定义的呢?

 TagKey属性专门定义最外层的元素

图一

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
protected 
virtual HtmlTextWriterTag TagKey
{
    
get
    
{
        return 
this.tagKey;
    }

}

TagKey的“value==null”的时候,TagName派上用场了,这时我们就可以自定义一些系统没有的元素了,注意她是字符串类型!

图二

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
protected virtual 
string TagName
{
    
get
    
{
        if ((this.tagName == null&& (this.TagKey 
!= HtmlTextWriterTag.Unknown))
        
{
            this.tagName = Enum.Format(typeof(HtmlTextWriterTag), this.TagKey, "G
").ToLower(CultureInfo.InvariantCulture);
        }

        return this.tagName;
    }

}

那么最外层元素的属性和样式是怎样定义的呢?当然是AddAttributesToRender方法了,由于此方法的内部实现比较复杂,在此就不列出来了!只要明白一点,她是为最外层元素服务的!并且在先于RenderContents方法调用!还记得我们在重写Control的时候,先定义控件的属性和样式,然后才定义控件的元素,记得否?我还是贴一张图吧,有时候我也这样健忘J

图三

writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0");
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
//

        二,WebControl用来呈现内容的方法是怎样定义的呢?
首先重写了ControlRender方法
图四

protected internal override void Render(HtmlTextWriter writer)
{
    
this.RenderBeginTag(writer);
    
this.RenderContents(writer);
    
this.RenderEndTag(writer);
}

先看RenderContents方法,啥也没干,就调用基类的virtual Render方法!
图五

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


 

 

再看看RenderBeginTagRenderEndTag方法,有点意思哦!

图六

public virtual void RenderBeginTag(HtmlTextWriter writer)
{
    
this.AddAttributesToRender(writer);
    HtmlTextWriterTag tagKey = 
this.TagKey;
    if (tagKey 
!= HtmlTextWriterTag.Unknown)
    
{
        writer.RenderBeginTag(tagKey);
    }

    
else
    
{
        writer.RenderBeginTag(
this.TagName);
    }

}

图七

public virtual void RenderEndTag(HtmlTextWriter writer)
{
    writer.RenderEndTag();
}

看到了吗?所有的最外层的元素,属性,和样式都在此做完了!(没错,我前面说过AddAttributesToRender方法在RenderContents之前被调用!),还要注意一点的就是

writer.RenderBeginTag(tagKey)writer.RenderEndTag()方法都是HtmlTextWriter对象的方法,而非WebControl本身的方法!

    虽然,这种“记流水帐形式”的文风,有点“那个”,但只要能说清楚问题,也就懒得在意了J

还是举个例子吧,免得有人说我懒(我妈说我懒)

下面的demo呈现一个Lable,重写最外层元素spanDiv,背景色为红色,并在Lable的内容中加一个背景色为蓝色的Div,就这么简单!

图八

using System;
using System.Web.UI;
using System.ComponentModel;
using System.Web.UI.WebControls;

namespace ClassLibrary1
{
    [DefaultPropertyAttribute("Text
")]
    [ToolboxData(@"<{0}:WMJLable Text='哈哈' name='小声的笑' runat='server'></{0}:WMJLable>
")]

    public 
class WMJLable:WebControl
    
{
        //
字段
        string _text = 
string.Empty;
        string _name = 
string.Empty;
        //
属性
        public 
string Text
        
{
            
get 
            
{
                if (ViewState["Text"== 
null)
                    return 
"";
                
else
                    return ViewState["Text
"].ToString();
                
            }

            
set 
            
{
                ViewState["Text"
= value;   
            }

        }

        public string Name
        
{
            
get 
            
{
                if (ViewState["Name"== 
null)
                    return 
"";
                
else
                    return ViewState["Name
"].ToString();
            }

            
set 
            
{
                ViewState["Name"
= value;
            }

        }

        //重写最外层标签,默认为SPAN
        protected 
override HtmlTextWriterTag TagKey
        
{
            get 
return HtmlTextWriterTag.Div; }
        }


        //
重写最外层标签Div的样式属性,把边框色弄成红色
        protected override 
void AddAttributesToRender(HtmlTextWriter writer)
        
{
            
base.AddAttributesToRender(writer);
            writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "Red
");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "400px
");
        }


        protected
 override void RenderContents(HtmlTextWriter writer)
        
{
            
base.RenderContents(writer);

            writer.Write(Text);
            writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "Blue
");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "300px
");
            writer.AddAttribute(HtmlTextWriterAttribute.Name, Name);
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.RenderEndTag() ;
            
        }

    }

}

效果图

参考
Clingingboy

posted on 2008-03-18 00:34 王孟军! 阅读(2117) 评论(3)  编辑 收藏 所属分类: asp.net Controls

评论

#1楼  2008-03-18 08:51 风之影      
关键是理解控件的生命周期,写的还不错
  回复  引用  查看    

#2楼  2008-03-18 14:43 老夫子系      
WebControl 的呈现,是否可以用HTML来显示。
如果我们画一个表格,不用C#代码一行一行的输出HTML代码、样式等等。

方法当然是有的,
在 2.0 中,有一个ParseControl方法。
MSDN是这么解释的:将输入字符串分析为 Web 窗体页或用户控件上的 Control 对象。

所以在我们的自定义用户控件中,先定义一段HTML的字符串,然后在 Control_Init事件中,输出HTML字符串的控件。
如:Control Selector = Page.ParseControl(_WebHTML);

  回复  引用  查看    

#3楼 [楼主] 2008-03-19 08:29 王孟军!      
@老夫子系
从设计角度讲,使用你那种方法,有点走”回头路“的感觉
  回复  引用  查看