原文地址:https://www.cnblogs.com/kingthy/archive/2009/09/04/net-vtemplate-doc-4.html
在網站中,經常會有某個欄目的數據在多個頁面同時使用到。比如新聞網站或電子商務網站的欄目列表,幾乎在很多頁面都會顯示欄目導航。對於這種多個頁面同時使用到的“數據區”在ASP.NET Web Form開發中,經常會將這些“數據區”獨立封裝爲一個個Web控件。那在VTemplate模板引擎裏又要如何做呢?在VTemplate模板引擎裏,提供了一種“模板塊解析器”接口。當VTemplate模板引擎解析並呈現VT模板數據時,如果發現某個<vt:template>標籤已定義“模板塊解析器”,則會構建此“模板塊解析器”實例並將解析權交給“模板塊解析器”,等其處理完後再繼續解析呈現標籤數據。其流程圖如下:
在<vt:template>標籤使用“模板塊解析器”,是利用其已定義的兩個特殊屬性:
名稱 | 說明 |
render | 定義用於處理此模塊數據的實例,格式:"類實例,程序集"。如果已定義此屬性但未定義rendermethod屬性,則類實例必須已實現ITemplateRender接口。(可不定義) |
rendermethod | 定義用於處理此模塊數據的類實例的方法,此方法必須已標記TemplateRenderMethodAttribute特性。(可不定義) |
如果是使用ITemplateRender接口來實現“模板塊解析器”,則只需要定義render屬性;如果用TemplateRenderMethodAttribute特性來實現“模板塊解析器”,則必須要定義render和rendermethod方法!
注意:TemplateRenderMethodAttribute特性的優先權最高,即如果同時定義了這兩個屬性,則不管render定義的類是否已實現ITemplateRender接口都會被忽略不用,而直接使用rendermethod定義的特性方法!
1、ITemplateRender接口。
/// <summary>
/// 模板塊數據的解析處理接口
/// </summary>
public interface ITemplateRender
{
/// <summary>
/// 預處理解析模板數據
/// </summary>
/// <param name="template"></param>
void PreRender(Template template);
}從上可知,ITemplateRender接口只有一個聲明方法PreRender,用於接收處理VTemplate模板引擎轉交過來要進行解析的模板塊。
我們將《VTemplate模板引擎的使用--進階篇》的最後一個例子改一下,用ITemplateRender接口來處理那些新聞列表數據。
我們先構建一個已實現ITemplateRender接口的類,代碼如下:
namespace VTemplate.WebTester.Core { /// <summary> /// 模板塊解析器 /// </summary> public class CnblogsNewsRender : ITemplateRender { #region ITemplateRender 成員 /// <summary> /// 解析某個模板塊的數據 /// </summary> /// <param name="template"></param> public void PreRender(Template template) { //根據模板塊裏定義的type屬性條件取得新聞數據 List<News> newsData = NewsDbProvider.GetNewsData(template.Attributes.GetValue("type")); //設置變量newsdata的值 template.Variables.SetValue("newsdata", newsData); //取得模板塊下Id爲newslist的標籤(也即是在cnblogs_newsdata.html文件中定義的foreach標籤) Tag tag = template.GetChildTagById("newslist"); if (tag is ForEachTag) { //如果標籤爲foreach標籤則設置其BeforeRender事件用於設置變量表達式{$:#.news.url}的值 tag.BeforeRender += (sender, e) => { ForEachTag t = (ForEachTag)sender; //取得當前項的值(因爲foreach標籤的數據源是List<News>集合,所以當前項的值類型爲News實體) News news = (News)t.Item.Value; //設置當前項的變量表達式的值.也即是"{$:#.news.url}"變量表達式 t.Item.SetExpValue("url", NewsDbProvider.GetNewsUrl(news)); //當新聞不可見時.你可以取消本次輸出 if (!news.Visible) e.Cancel = true; }; } } #endregion } }這樣我們就構造了一個“模板塊解析器”,在VT模板裏就可以直接使用了,如下:
<div class="side_block">
<h3 class="title_blue">相關新聞</h3>
<vt:template name="topnews" type="relating" file="cnblogs_newsdata.html" render="VTemplate.WebTester.Core.CnblogsNewsRender,VTemplate.WebTester" />
</div>
<div class="side_block">
<h3 class="title_yellow">熱點新聞</h3>
<vt:template name="topnews" type="hoting" file="cnblogs_newsdata.html" render="VTemplate.WebTester.Core.CnblogsNewsRender,VTemplate.WebTester" />
</div>具體的示例代碼,請參考:http://net-vtemplate.googlecode.com/svn/src/VTemplate.WebTester/templaterender_test.ashx.cs
2、TemplateRenderMethodAttribute特性方法
TemplateRenderMethodAttribute特性方法的原形和ITemplateRender接口的PreRender差不多,即只能有一個參數,用於接收VTemplate模板引擎轉交過來要進行解析的模板塊對象。如下面例子代碼:
/// <summary> /// 解析某個模板塊的數據 /// </summary> /// <param name="template"></param> [TemplateRenderMethod(Description="解析新聞列表數據")] public void RenderNews(Template template) {}而VT模板代碼就需要定義<vt:template>的rendermethod屬性,並且定義的值必須和類代碼中的方法名一致,如下面例子代碼:
<div class="side_block">
<h3 class="title_blue">相關新聞</h3>
<vt:template name="topnews" type="relating" file="cnblogs_newsdata.html" render="VTemplate.WebTester.Core.CnblogsNewsRenderMethod,VTemplate.WebTester" rendermethod="RenderNews" />
</div>
<div class="side_block">
<h3 class="title_yellow">熱點新聞</h3>
<vt:template name="topnews" type="hoting" file="cnblogs_newsdata.html" render="VTemplate.WebTester.Core.CnblogsNewsRenderMethod,VTemplate.WebTester" rendermethod="RenderNews" />
</div>
具體的示例代碼,請參考:http://net-vtemplate.googlecode.com/svn/src/VTemplate.WebTester/templaterendermethod_test.ashx.cs
TemplateRenderMethodAttribute特性方法與ITemplateRender接口比較,它的好處就是可在一個類實例中定義多個方法用於處理不同的模板塊,也即是說可在一個類實例裏定義多個“模板塊解析器”。