petshop4.0 详解之六(PetShop表示层设计)(2)

来源:互联网 发布:舒特一卡通软件3.3 编辑:程序博客网 时间:2024/05/16 06:38
petshop4.0 详解之六(PetShop表示层设计)(2)
2007-09-12 16:14

在这里,控件设计利用了Template Method模式,Control基类提供了大部分protected虚方法,留待其子类改写其方法。以PetShop 4.0为例,就定义了两个ASP.NET控件,它们都属于System.Web.UI.WebControls.WebControl的子类。其中,CustomList控件派生自System.Web.UI.WebControls.DataList,CustomGrid控件则派生自System.Web.UI.WebControls.Repeater。

由于这两个控件都改变了其父类控件的呈现方式,故而,我们可以通过重写父类的Render虚方法,完成控件的自定义。例如CustomGrid控件:

public class CustomGrid : Repeater…
//Static constants
    protected const string HTML1 = "<table cellpadding=0
cellspacing=0><tr><td colspan=2>";
    protected const string HTML2 = "</td></tr><tr><td class=paging align=left>";
    
protected const string HTML3 = "</td><td align=right class=paging>";
    
protected const string HTML4 = "</td></tr></table>";
    
private static readonly Regex RX = new Regex(@"^&page=/d+",
RegexOptions.Compiled);
    
private const string LINK_PREV = "<a href=?page={0}>&#060;&nbsp;Previous</a>";
    
private const string LINK_MORE = "<a href=?page={0}>More&nbsp;&#062;</a>";
private const string KEY_PAGE = "page";
    
private const string COMMA = "?";
    
private const string AMP = "&";

override protected void Render(HtmlTextWriter writer) {

        
//Check there is some data attached
        if (ItemCount == 0) {
             writer.Write(emptyText);
            
return;
         }

        
//Mask the query
        string query = Context.Request.Url.Query.Replace(COMMA, AMP);
         query
= RX.Replace(query, string.Empty);
        
// Write out the first part of the control, the table header
         writer.Write(HTML1);
        
// Call the inherited method
        base.Render(writer);
        
// Write out a table row closure
         writer.Write(HTML2);
        
//Determin whether next and previous buttons are required
        
//Previous button?
        if (currentPageIndex > 0)
             writer.Write(
string.Format(LINK_PREV, (currentPageIndex - 1) + query));
        
//Close the table data tag
         writer.Write(HTML3);

        
//Next button?
        if (currentPageIndex < PageCount)
             writer.Write(
string.Format(LINK_MORE, (currentPageIndex + 1) + query));

        
//Close the table
         writer.Write(HTML4);
     }

由于CustomGrid继承自Repeater控件,因而它同时还继承了Repeater的DataSource属性,这是一个虚属性,它默认的set访问器属性如下:

public virtual object DataSource
{
      
get  {… }
      
set
      
{
            
if (((value != null) && !(value is IListSource)) && !(value is IEnumerable))
            
{
                  
throw new ArgumentException(SR.GetString("Invalid_DataSource_Type", new object[] { this.ID }));
             }

            
this.dataSource = value;
            
this.OnDataPropertyChanged();
       }

}

对于CustomGrid而言,DataSource属性有着不同的设置行为,因而在定义CustomGrid控件的时候,需要改写DataSource虚属性,如下所示:

private IList dataSource;
private int itemCount;

override public object DataSource {
    
set {
    
//This try catch block is to avoid issues with the VS.NET designer
        
//The designer will try and bind a datasource which does not derive from ILIST
        try {
             dataSource
= (IList)value;
             ItemCount
= dataSource.Count;
         }

        
catch {
             dataSource
= null;
             ItemCount
= 0;
         }

     }

}
 
原创粉丝点击