ASP.NET模板控件开发浅析

开发 后端
ASP.NET模板控件那么呢?首先本文从了解ASP.NET模板控件开始向你介绍了ASP.NET模板控件的先关内容。

本文主题是ASP.NET模板控件,模板控件将是复杂控件的起步

ASP.NET模板控件1.ASP.NET内置的模板控件,了解模板控件

如下图,以下为ASP.NET内置的模板控件

ASP.NET内置的模板控件 

上图的控件一方面是模板控件,另一方面又是数据绑定控件.这里我们暂且不讨论如何实现数据绑定.

使用上面控件的话,应该熟悉控件存在着不同的模板,如下图Repeater控件的模板类型.

Repeater控件的模板类型 

在不同模板内你可以定义控件显示内容会呈现不同效果.典型的运用就是GridView,其呈现代码会是一个表格代码,而Repeater则是自定义的.其实其是内部已经实现了的,暂且先不管这些.下面一步步看下来如何实现.

ASP.NET模板控件2.实现模板控件

2.1简单实现模板控件(静态模板)

(1)模板控件为特殊的复合控件,你还是需要实现INamingContainer接口,因为在模板属性的内容是为子控件集合添加到模板控件中,为保证控件具有唯一标识符.其实现将在CreateChildControls方法中创建子控件.

ASP.NET中可以直接继续CompositeControl就可

(2)定义控件属性

模板属性为System.Web.UI.ITemplate 接口,此接口有一InstantiateIn 方法 将在下面分析

上一篇我们说明了控件内部属性和控件的区别,模板并非控件而是属性,我们在属性浏览器中并未看到此属性,是因为我们为其加了元数据,作为内部属性使用

定义模板属性方法如下

  1. //声明变量  
  2. private ITemplate _itemTemplate;  
  3.  
  4.  
  5. //属性  
  6. [Browsable(false)]  
  7. [TemplateContainer(typeof(Article))]  
  8. [PersistenceMode(PersistenceMode.InnerProperty)]  
  9. public ITemplate ItemTemplate  
  10. {  
  11.     get { return _itemTemplate; }  
  12.     set { _itemTemplate = value; }  

这里我们认识到了一个TemplateContainer元数据,其与容器控件关联起来.Article为默认其自身控件,即默认将自身控件作为容器控件.

(3).重写CreateChildControls方法

此方法我们以前已认识过了,主要是为控件添加子控件

  1. protected override void CreateChildControls()  
  2. {  
  3.     _itemTemplate.InstantiateIn(this);  

这次我们要做的重点是认识ITemplate接口的InstantiateIn 方法,方法有一个Control参数,其为子控件和模板定义了一个容器控件(此处为其自身控件,下面看页面代码).如GridView和DataList控件都实现了自定义的容器控件.Repeater则是完全自定义的.这里暂且默认实现

ASP.NET模板控件实现代码

在模板内拖了一个label控件

  1. ﹤custom:Article  
  2.     id="Article1" 
  3.     Runat="server"﹥  
  4.     ﹤ItemTemplate﹥  
  5.     ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥﹤/asp:Label﹥  
  6.     ﹤/ItemTemplate﹥  
  7. ﹤/custom:Article﹥  

OK,你可以看一下效果了,当然你可以定义多个模板然后在多个不同模板内添加内容.我们来看下其控件树内容,如下图

控件树 

子控件有一个Label控件,非控件内容则以LiteralControl呈现.

2.2实现动态模板

当我们使用DataList控件时,往往在模板中动态的绑定一些数据,获取的这些数据则是ITemplate接口的InstantiateIn 方法中的容器控件.下面我们为控件定义属性,然后通过DataBind()方法和数据绑定表达式获取数据

我们先先定义三个属性

页面代码,注意要用DataBind()方法

  1. void Page_Load()  
  2. {  
  3.     Article1.Title = "Creating Templated Databound Controls";  
  4.     Article1.Author = "Stephen Walther";  
  5.     Article1.Contents = "Blah, blah, blah, blah";  
  6.     Article1.DataBind();  

通过Container数据绑定表达式获取容器对象属性,此处容器对象为默认的Article

容器对象为默认的Article 

如下实现

  1. ﹤custom:Article  
  2.     id="Article1" 
  3.     Runat="server"﹥  
  4.     ﹤ItemTemplate﹥  
  5.     ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥﹤/asp:Label﹥  
  6.     ﹤%# Container.Title%﹥﹤br /﹥  
  7.     ﹤%# Container.Author %﹥﹤br /﹥  
  8.     ﹤%# Container.Contents %﹥﹤br /﹥  
  9.     ﹤/ItemTemplate﹥  
  10. ﹤/custom:Article﹥ 

好了,到这里你就实现了一个简单的动态模板控件了.

2.3实现默认模板

在购书网站上我们常常看到由于图书太多的情况下,管理人员未能将图书封面发布到网站上,这时此书可能出现默认的图片"尚为此书添加图书封面"

在一个具有模板的控件里,如果你未为控件添加模板属性的话,你可以通过实现默认模板来实现默认效果.

(1)那你第一步要做的就是定义一个自定义ASP.NET模板控件.此模板需要实现ITemplate接口,实现InstantiateIn方法.看一下典型实现,如下代码

  1. public class ArticleDefaultTemplate : ITemplate  
  2. {  
  3.     public void InstantiateIn(Control container)  
  4.     {  
  5.         Label lblTitle = new Label();  
  6.         lblTitle.DataBinding += new EventHandler(lblTitle_DataBinding);  
  7.  
  8.         Label lblAuthor = new Label();  
  9.         lblAuthor.DataBinding += new EventHandler(lblAuthor_DataBinding);  
  10.  
  11.         Label lblContents = new Label();  
  12.         lblContents.DataBinding += new EventHandler(lblContents_DataBinding);  
  13.  
  14.         container.Controls.Add(lblTitle);  
  15.         container.Controls.Add(new LiteralControl("﹤br /﹥"));  
  16.         container.Controls.Add(lblAuthor);  
  17.         container.Controls.Add(new LiteralControl("﹤br /﹥"));  
  18.         container.Controls.Add(lblContents);  
  19.     }  
  20.  
  21.     void lblTitle_DataBinding(object sender, EventArgs e)  
  22.     {  
  23.         Label lblTitle = (Label)sender;  
  24.         ArticleWithDefault container = (ArticleWithDefault)lblTitle.NamingContainer;  
  25.         lblTitle.Text = container.Title;  
  26.     }  
  27.  
  28.     void lblAuthor_DataBinding(object sender, EventArgs e)  
  29.     {  
  30.         Label lblAuthor = (Label)sender;  
  31.         ArticleWithDefault container = (ArticleWithDefault)lblAuthor.NamingContainer;  
  32.         lblAuthor.Text = container.Author;  
  33.     }  
  34.  
  35.     void lblContents_DataBinding(object sender, EventArgs e)  
  36.     {  
  37.         Label lblContents = (Label)sender;  
  38.         ArticleWithDefault container = (ArticleWithDefault)lblContents.NamingContainer;  
  39.         lblContents.Text = container.Contents;  
  40.     }  
  41.  

在InstantiateIn方法中,定义了默认控件,并实现了默认绑定.在各自的数据绑定事件里通过容器控件(默认容器控件为ArticleWithDefault,此处还是没自定义容器控件,下面会介绍)的NamingContainer属性获取控件ID值.然后对控件进行赋值.

(2)重写CreateChildControls方法

当未定义模板属性时,则实现默认模板

  1. protected override void CreateChildControls()  
  2. {  
  3.     if (_itemTemplate == null)  
  4.         _itemTemplate = new ArticleDefaultTemplate();  
  5.     _itemTemplate.InstantiateIn(this);  

(3)页面代码

下面实现效果跟2.2的定义的模板控件效果一样,这里只为说明默认模板的使用方法

  1. void Page_Load()  
  2. {  
  3.     ArticleWithDefault1.Title = "Creating Templated Databound Controls";  
  4.     ArticleWithDefault1.Author = "Stephen Walther";  
  5.     ArticleWithDefault1.Contents = "Blah, blah, blah, blah";  
  6.     ArticleWithDefault1.DataBind();  
  7. }  
  8.  
  9. ﹤custom:ArticleWithDefault  
  10.     id="ArticleWithDefault1" 
  11.     Runat="server" /﹥ 

2.4ASP.NET模板控件之实现自定义容器控件

上面我已经多次注明容器控件为默认自身控件,你可以通过自定义容器控件

GridView控件会自动把数据以表格形式呈现,DataList控件有DataListItem ,Repeater则有RepeaterItem.

这些控件实现数据绑定后,通常不是显示一条数据的,其控件都有一个Items属性,其表示项集合.

每项数据都在其Item里面,看一下DataList绑定数据以后的控件树

绑定数据以后的控件 

我们常常会需要在模板控件里以以下方式来获取模板内部控件

如在DataList控件中

  1. protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)  
  2. {  
  3.     e.Item.FindControl("");  
  4.     DataList1.Items[0].BackColor = System.Drawing.Color.Red;  

通过此方法我们可以处理一些特殊的列和行.为实现上面效果,我们也可以为ASP.NET模板控件自定义容器控件

(1)自定义容器控件类

注意需要实现IDataItemContainer接口,就如DataList一样,其绑定的数据不可能是一条的.

  1. public class ProductItem : WebControl, IDataItemContainer  
  2.  {  
  3.      private string _name;  
  4.      private decimal _price;  
  5.  
  6.      public string Name  
  7.      {  
  8.          get { return _name; }  
  9.          set { _name = value; }  
  10.      }  
  11.  
  12.      public decimal Price  
  13.      {  
  14.          get { return _price; }  
  15.          set { _price = value; }  
  16.      }  
  17.  
  18.      public object DataItem  
  19.      {  
  20.          get 
  21.          {  
  22.              return this;  
  23.          }  
  24.      }  
  25.  
  26.      public int DataItemIndex  
  27.      {  
  28.          get { return 0; }  
  29.      }  
  30.  
  31.      public int DisplayIndex  
  32.      {  
  33.          get { return 0; }  
  34.      }  
  35.  } 

然后在主控件中如下实现

  1. private ProductItem _item;  
  2.  
  3.   public string Name  
  4.   {  
  5.       get 
  6.       {  
  7.           EnsureChildControls();  
  8.           return _item.Name;  
  9.       }  
  10.       set 
  11.       {  
  12.           EnsureChildControls();  
  13.           _item.Name = value;  
  14.       }  
  15.   }  
  16.  
  17.   public Decimal Price  
  18.   {  
  19.       get 
  20.       {  
  21.           EnsureChildControls();  
  22.           return _item.Price;  
  23.       }  
  24.       set 
  25.       {  
  26.           EnsureChildControls();  
  27.           _item.Price = value;  
  28.       }  
  29.   } 

(2)ASP.NET模板控件之用TemplateContainer与模板属性关联起来

  1. [TemplateContainer(typeof(ProductItem))]  
  2. [PersistenceMode(PersistenceMode.InnerProperty)]  
  3. public ITemplate ItemTemplate  
  4. {  
  5.     get { return _itemTemplate; }  
  6.     set { _itemTemplate = value; }  

(3)重写CreateChildControls方法

注意了,此处模板的InstantiateIn方法不再是this了,而是自定义容器控件了,再用数据绑定表达式访问的将是ProductItem的数据(即自定义容器控件的数据)

  1. protected override void CreateChildControls()  
  2. {  
  3.     _item = new ProductItem();  
  4.     _itemTemplate.InstantiateIn(_item);  
  5.     Controls.Add(_item);  

(4)页面代码

  1. void Page_Load()  
  2. {  
  3.     Product1.Name = "Laptop Computer";  
  4.     Product1.Price = 1254.12m;  
  5.     Product1.DataBind();  
  6. }  
  7.  
  8. ﹤custom:Product  
  9.     id="Product1" 
  10.     Runat="Server"﹥  
  11.     ﹤ItemTemplate﹥  
  12.      
  13.     Name: ﹤%# Eval("Name") %﹥  
  14.     ﹤br /﹥  
  15.     Price: ﹤%# Eval("Price""{0:c}") %﹥   
  16.     ﹤/ItemTemplate﹥      
  17. ﹤/custom:Product﹥ 

上面以Eval来绑定数据,也可以用Container表达式,如下图,其类型为ProductItem

类型为ProductItem 

注意:当不是数据绑定控件时,则不能用Eval绑定语法,如上面的几个例子.大家可以测试一下.

ASP.NET模板控件的相关内容就向你介绍到这里,希望对你了解ASP.NET模板控件有所帮助。

【编辑推荐】

  1. ASP.NET控件开发基础之自定义视图状态管理
  2. ASP.NET控件开发基础之为子控件添加样式
  3. ASP.NET控件开发基础之服务器控件客户端功能
  4. ASP.NET控件开发之控件生成器浅析
  5. ASP.NET控件开发基础的总结详解
责任编辑:仲衡 来源: 博客园
相关推荐

2009-08-07 15:34:15

ASP.NET数据绑定

2009-07-27 17:25:53

ASP.NET验证控件

2009-08-06 18:18:27

ASP.NET控件开发ASP.NET复合控件

2009-08-06 15:21:45

ASP.NET控件开发RenderConte

2009-07-28 09:32:41

ASP.NET自定义控

2009-08-07 14:05:21

ASP.NET控件

2009-08-07 17:49:44

控件设计器

2009-08-05 18:46:21

ComboBox显示ASP.NET控件开发

2009-08-06 13:08:23

ASP.NET控件开发

2009-08-07 17:17:43

ASP.NET控件设计

2009-08-06 09:18:01

ASP.NET自定义控ASP.NET控件开发

2009-08-05 18:32:28

HtmlTextWriASP.NET控件开发

2009-08-06 18:32:00

ASP.NET控件开发ASP.NET复合控件

2009-08-05 17:11:51

ASP.NET控件开发ASP.NET服务器控

2009-08-07 17:59:35

控件设计器

2009-08-07 16:32:52

ASP.NET控件设计时支

2009-07-24 09:57:25

ASP.NET HTM

2009-08-04 15:20:59

ASP.NET数据验证数据验证控件

2009-08-04 10:43:59

ASP.NET控件开发

2009-07-28 16:21:03

Asp.net AjaAutoComplet
点赞
收藏

51CTO技术栈公众号