VTemplate模板引擎的使用--高级篇

在网站中,经常会有某个栏目的数据在多个页面同时使用到。比如新闻网站或电子商务网站的栏目列表,几乎在很多页面都会显示栏目导航。对于这种多个页面同时使用到的“数据区”在ASP.NET Web Form开发中,经常会将这些“数据区”独立封装为一个个Web控件。那在VTemplate模板引擎里又要如何做呢?在VTemplate模板引擎里,提供了一种“模板块解析器”接口。当VTemplate模板引擎解析并呈现VT模板数据时,如果发现某个<vt:template>标签已定义“模板块解析器”,则会构建此“模板块解析器”实例并将解析权交给“模板块解析器”,等其处理完后再继续解析呈现标签数据。其流程图如下:

vtemplate_snap_doc3_1

 

在<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接口比较,它的好处就是可在一个类实例中定义多个方法用于处理不同的模板块,也即是说可在一个类实例里定义多个“模板块解析器”。

 

VTemplate项目托管在Google code上
URL: http://net-vtemplate.googlecode.com/
SVN: http://net-vtemplate.googlecode.com/svn/src/VTemplate.Engine/

更多例子请参考VTemplate.WebTester项目

http://net-vtemplate.googlecode.com/svn/src/VTemplate.WebTester/

或观看在线演示例子:(感谢网友“DOLT”、疯子提供

http://61.155.39.222:8888/index.ashx

注:已建立VTemplate模板引擎技术交流QQ群,欢迎各位加入参与项目开发或技术探讨。QQ群:884468

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 Microsoft Office 提供的 COM 接口来实现将数据保存到 Word 表格中的功能。以下是一个简单的示例程序: ```cpp #include <windows.h> #include <ole2.h> #include <atlbase.h> #include <atlcom.h> #include <atlcomcli.h> int main() { CoInitialize(NULL); // 创建 Word 应用程序对象 CComPtr<IDispatch> pWordApp; HRESULT hr = pWordApp.CoCreateInstance(CLSID_WordApplication); if (FAILED(hr)) { CoUninitialize(); return 1; } // 获取 Documents 对象 CComPtr<IDispatch> pDocuments; hr = pWordApp->get_Documents(&pDocuments); if (FAILED(hr)) { CoUninitialize(); return 1; } // 新建一个文档 CComVariant vTemplate(DISP_E_PARAMNOTFOUND, VT_ERROR); CComVariant vFalse(VARIANT_FALSE); CComPtr<IDispatch> pDoc; hr = pDocuments->Add(&vTemplate, &vFalse, &vFalse, &pDoc); if (FAILED(hr)) { CoUninitialize(); return 1; } // 获取 Tables 对象 CComPtr<IDispatch> pTables; hr = pDoc->get_Tables(&pTables); if (FAILED(hr)) { CoUninitialize(); return 1; } // 在文档中添加一个表格 CComVariant vTableRow(3); CComVariant vTableColumn(3); CComPtr<IDispatch> pTable; hr = pTables->Add(CComVariant(pDoc), vTableRow, vTableColumn, &pTable); if (FAILED(hr)) { CoUninitialize(); return 1; } // 设置表格内容 CComPtr<IDispatch> pRange; hr = pTable->get_Range(&pRange); if (FAILED(hr)) { CoUninitialize(); return 1; } CComBSTR bstrText(L"1"); hr = pRange->put_Text(bstrText); if (FAILED(hr)) { CoUninitialize(); return 1; } // 保存文档 CComVariant vDocName(L"D:\\table.docx"); hr = pDoc->SaveAs(&vDocName, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &vFalse, &pRange); if (FAILED(hr)) { CoUninitialize(); return 1; } // 关闭 Word 应用程序 hr = pWordApp->Quit(&vFalse, &vFalse, &vFalse); if (FAILED(hr)) { CoUninitialize(); return 1; } CoUninitialize(); return 0; } ``` 这个示例程序新建了一个文档,并在其中添加了一个 3x3 的表格,并将第一个单元格的文本设置为 "1",最后将文档保存到指定路径。你可以根据需要修改程序中的内容。注意,在使用 COM 接口时,需要注意内存管理问题,避免内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值