ASP.NET模板控件開(kāi)發(fā)淺析
本文主題是ASP.NET模板控件,模板控件將是復(fù)雜控件的起步
ASP.NET模板控件1.ASP.NET內(nèi)置的模板控件,了解模板控件
如下圖,以下為ASP.NET內(nèi)置的模板控件
上圖的控件一方面是模板控件,另一方面又是數(shù)據(jù)綁定控件.這里我們暫且不討論如何實(shí)現(xiàn)數(shù)據(jù)綁定.
使用上面控件的話,應(yīng)該熟悉控件存在著不同的模板,如下圖Repeater控件的模板類(lèi)型.
在不同模板內(nèi)你可以定義控件顯示內(nèi)容會(huì)呈現(xiàn)不同效果.典型的運(yùn)用就是GridView,其呈現(xiàn)代碼會(huì)是一個(gè)表格代碼,而Repeater則是自定義的.其實(shí)其是內(nèi)部已經(jīng)實(shí)現(xiàn)了的,暫且先不管這些.下面一步步看下來(lái)如何實(shí)現(xiàn).
ASP.NET模板控件2.實(shí)現(xiàn)模板控件
2.1簡(jiǎn)單實(shí)現(xiàn)模板控件(靜態(tài)模板)
(1)模板控件為特殊的復(fù)合控件,你還是需要實(shí)現(xiàn)INamingContainer接口,因?yàn)樵谀0鍖傩缘膬?nèi)容是為子控件集合添加到模板控件中,為保證控件具有唯一標(biāo)識(shí)符.其實(shí)現(xiàn)將在CreateChildControls方法中創(chuàng)建子控件.
ASP.NET中可以直接繼續(xù)CompositeControl就可
(2)定義控件屬性
模板屬性為System.Web.UI.ITemplate 接口,此接口有一InstantiateIn 方法 將在下面分析
上一篇我們說(shuō)明了控件內(nèi)部屬性和控件的區(qū)別,模板并非控件而是屬性,我們?cè)趯傩詾g覽器中并未看到此屬性,是因?yàn)槲覀優(yōu)槠浼恿嗽獢?shù)據(jù),作為內(nèi)部屬性使用
定義模板屬性方法如下
- //聲明變量
- private ITemplate _itemTemplate;
- //屬性
- [Browsable(false)]
- [TemplateContainer(typeof(Article))]
- [PersistenceMode(PersistenceMode.InnerProperty)]
- public ITemplate ItemTemplate
- {
- get { return _itemTemplate; }
- set { _itemTemplate = value; }
- }
這里我們認(rèn)識(shí)到了一個(gè)TemplateContainer元數(shù)據(jù),其與容器控件關(guān)聯(lián)起來(lái).Article為默認(rèn)其自身控件,即默認(rèn)將自身控件作為容器控件.
(3).重寫(xiě)CreateChildControls方法
此方法我們以前已認(rèn)識(shí)過(guò)了,主要是為控件添加子控件
- protected override void CreateChildControls()
- {
- _itemTemplate.InstantiateIn(this);
- }
這次我們要做的重點(diǎn)是認(rèn)識(shí)ITemplate接口的InstantiateIn 方法,方法有一個(gè)Control參數(shù),其為子控件和模板定義了一個(gè)容器控件(此處為其自身控件,下面看頁(yè)面代碼).如GridView和DataList控件都實(shí)現(xiàn)了自定義的容器控件.Repeater則是完全自定義的.這里暫且默認(rèn)實(shí)現(xiàn)
ASP.NET模板控件實(shí)現(xiàn)代碼
在模板內(nèi)拖了一個(gè)label控件
- ﹤custom:Article
- id="Article1"
- Runat="server"﹥
- ﹤ItemTemplate﹥
- ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥﹤/asp:Label﹥
- ﹤/ItemTemplate﹥
- ﹤/custom:Article﹥
OK,你可以看一下效果了,當(dāng)然你可以定義多個(gè)模板然后在多個(gè)不同模板內(nèi)添加內(nèi)容.我們來(lái)看下其控件樹(shù)內(nèi)容,如下圖
子控件有一個(gè)Label控件,非控件內(nèi)容則以LiteralControl呈現(xiàn).
2.2實(shí)現(xiàn)動(dòng)態(tài)模板
當(dāng)我們使用DataList控件時(shí),往往在模板中動(dòng)態(tài)的綁定一些數(shù)據(jù),獲取的這些數(shù)據(jù)則是ITemplate接口的InstantiateIn 方法中的容器控件.下面我們?yōu)榭丶x屬性,然后通過(guò)DataBind()方法和數(shù)據(jù)綁定表達(dá)式獲取數(shù)據(jù)
我們先先定義三個(gè)屬性
頁(yè)面代碼,注意要用DataBind()方法
- void Page_Load()
- {
- Article1.Title = "Creating Templated Databound Controls";
- Article1.Author = "Stephen Walther";
- Article1.Contents = "Blah, blah, blah, blah";
- Article1.DataBind();
- }
通過(guò)Container數(shù)據(jù)綁定表達(dá)式獲取容器對(duì)象屬性,此處容器對(duì)象為默認(rèn)的Article
如下實(shí)現(xiàn)
- ﹤custom:Article
- id="Article1"
- Runat="server"﹥
- ﹤ItemTemplate﹥
- ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥﹤/asp:Label﹥
- ﹤%# Container.Title%﹥﹤br /﹥
- ﹤%# Container.Author %﹥﹤br /﹥
- ﹤%# Container.Contents %﹥﹤br /﹥
- ﹤/ItemTemplate﹥
- ﹤/custom:Article﹥
好了,到這里你就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的動(dòng)態(tài)模板控件了.
2.3實(shí)現(xiàn)默認(rèn)模板
在購(gòu)書(shū)網(wǎng)站上我們常??吹接捎趫D書(shū)太多的情況下,管理人員未能將圖書(shū)封面發(fā)布到網(wǎng)站上,這時(shí)此書(shū)可能出現(xiàn)默認(rèn)的圖片"尚為此書(shū)添加圖書(shū)封面"
在一個(gè)具有模板的控件里,如果你未為控件添加模板屬性的話,你可以通過(guò)實(shí)現(xiàn)默認(rèn)模板來(lái)實(shí)現(xiàn)默認(rèn)效果.
(1)那你第一步要做的就是定義一個(gè)自定義ASP.NET模板控件.此模板需要實(shí)現(xiàn)ITemplate接口,實(shí)現(xiàn)InstantiateIn方法.看一下典型實(shí)現(xiàn),如下代碼
- public class ArticleDefaultTemplate : ITemplate
- {
- public void InstantiateIn(Control container)
- {
- Label lblTitle = new Label();
- lblTitle.DataBinding += new EventHandler(lblTitle_DataBinding);
- Label lblAuthor = new Label();
- lblAuthor.DataBinding += new EventHandler(lblAuthor_DataBinding);
- Label lblContents = new Label();
- lblContents.DataBinding += new EventHandler(lblContents_DataBinding);
- container.Controls.Add(lblTitle);
- container.Controls.Add(new LiteralControl("﹤br /﹥"));
- container.Controls.Add(lblAuthor);
- container.Controls.Add(new LiteralControl("﹤br /﹥"));
- container.Controls.Add(lblContents);
- }
- void lblTitle_DataBinding(object sender, EventArgs e)
- {
- Label lblTitle = (Label)sender;
- ArticleWithDefault container = (ArticleWithDefault)lblTitle.NamingContainer;
- lblTitle.Text = container.Title;
- }
- void lblAuthor_DataBinding(object sender, EventArgs e)
- {
- Label lblAuthor = (Label)sender;
- ArticleWithDefault container = (ArticleWithDefault)lblAuthor.NamingContainer;
- lblAuthor.Text = container.Author;
- }
- void lblContents_DataBinding(object sender, EventArgs e)
- {
- Label lblContents = (Label)sender;
- ArticleWithDefault container = (ArticleWithDefault)lblContents.NamingContainer;
- lblContents.Text = container.Contents;
- }
- }
在InstantiateIn方法中,定義了默認(rèn)控件,并實(shí)現(xiàn)了默認(rèn)綁定.在各自的數(shù)據(jù)綁定事件里通過(guò)容器控件(默認(rèn)容器控件為ArticleWithDefault,此處還是沒(méi)自定義容器控件,下面會(huì)介紹)的NamingContainer屬性獲取控件ID值.然后對(duì)控件進(jìn)行賦值.
(2)重寫(xiě)CreateChildControls方法
當(dāng)未定義模板屬性時(shí),則實(shí)現(xiàn)默認(rèn)模板
- protected override void CreateChildControls()
- {
- if (_itemTemplate == null)
- _itemTemplate = new ArticleDefaultTemplate();
- _itemTemplate.InstantiateIn(this);
- }
(3)頁(yè)面代碼
下面實(shí)現(xiàn)效果跟2.2的定義的模板控件效果一樣,這里只為說(shuō)明默認(rèn)模板的使用方法
- void Page_Load()
- {
- ArticleWithDefault1.Title = "Creating Templated Databound Controls";
- ArticleWithDefault1.Author = "Stephen Walther";
- ArticleWithDefault1.Contents = "Blah, blah, blah, blah";
- ArticleWithDefault1.DataBind();
- }
- ﹤custom:ArticleWithDefault
- id="ArticleWithDefault1"
- Runat="server" /﹥
2.4ASP.NET模板控件之實(shí)現(xiàn)自定義容器控件
上面我已經(jīng)多次注明容器控件為默認(rèn)自身控件,你可以通過(guò)自定義容器控件
GridView控件會(huì)自動(dòng)把數(shù)據(jù)以表格形式呈現(xiàn),DataList控件有DataListItem ,Repeater則有RepeaterItem.
這些控件實(shí)現(xiàn)數(shù)據(jù)綁定后,通常不是顯示一條數(shù)據(jù)的,其控件都有一個(gè)Items屬性,其表示項(xiàng)集合.
每項(xiàng)數(shù)據(jù)都在其Item里面,看一下DataList綁定數(shù)據(jù)以后的控件樹(shù)
我們常常會(huì)需要在模板控件里以以下方式來(lái)獲取模板內(nèi)部控件
如在DataList控件中
- protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
- {
- e.Item.FindControl("");
- DataList1.Items[0].BackColor = System.Drawing.Color.Red;
- }
通過(guò)此方法我們可以處理一些特殊的列和行.為實(shí)現(xiàn)上面效果,我們也可以為ASP.NET模板控件自定義容器控件
(1)自定義容器控件類(lèi)
注意需要實(shí)現(xiàn)IDataItemContainer接口,就如DataList一樣,其綁定的數(shù)據(jù)不可能是一條的.
- public class ProductItem : WebControl, IDataItemContainer
- {
- private string _name;
- private decimal _price;
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- public decimal Price
- {
- get { return _price; }
- set { _price = value; }
- }
- public object DataItem
- {
- get
- {
- return this;
- }
- }
- public int DataItemIndex
- {
- get { return 0; }
- }
- public int DisplayIndex
- {
- get { return 0; }
- }
- }
然后在主控件中如下實(shí)現(xiàn)
- private ProductItem _item;
- public string Name
- {
- get
- {
- EnsureChildControls();
- return _item.Name;
- }
- set
- {
- EnsureChildControls();
- _item.Name = value;
- }
- }
- public Decimal Price
- {
- get
- {
- EnsureChildControls();
- return _item.Price;
- }
- set
- {
- EnsureChildControls();
- _item.Price = value;
- }
- }
(2)ASP.NET模板控件之用TemplateContainer與模板屬性關(guān)聯(lián)起來(lái)
- [TemplateContainer(typeof(ProductItem))]
- [PersistenceMode(PersistenceMode.InnerProperty)]
- public ITemplate ItemTemplate
- {
- get { return _itemTemplate; }
- set { _itemTemplate = value; }
- }
(3)重寫(xiě)CreateChildControls方法
注意了,此處模板的InstantiateIn方法不再是this了,而是自定義容器控件了,再用數(shù)據(jù)綁定表達(dá)式訪問(wèn)的將是ProductItem的數(shù)據(jù)(即自定義容器控件的數(shù)據(jù))
- protected override void CreateChildControls()
- {
- _item = new ProductItem();
- _itemTemplate.InstantiateIn(_item);
- Controls.Add(_item);
- }
(4)頁(yè)面代碼
- void Page_Load()
- {
- Product1.Name = "Laptop Computer";
- Product1.Price = 1254.12m;
- Product1.DataBind();
- }
- ﹤custom:Product
- id="Product1"
- Runat="Server"﹥
- ﹤ItemTemplate﹥
- Name: ﹤%# Eval("Name") %﹥
- ﹤br /﹥
- Price: ﹤%# Eval("Price", "{0:c}") %﹥
- ﹤/ItemTemplate﹥
- ﹤/custom:Product﹥
上面以Eval來(lái)綁定數(shù)據(jù),也可以用Container表達(dá)式,如下圖,其類(lèi)型為ProductItem
注意:當(dāng)不是數(shù)據(jù)綁定控件時(shí),則不能用Eval綁定語(yǔ)法,如上面的幾個(gè)例子.大家可以測(cè)試一下.
ASP.NET模板控件的相關(guān)內(nèi)容就向你介紹到這里,希望對(duì)你了解ASP.NET模板控件有所幫助。
【編輯推薦】