在Orchard CMS Theme 用代码定义布局Widgets
因为公司业务需要,经过本人几个月尝试,使用Orchard CMS 开发一个简单的企业门户(地址是http://www.ubof.cn)。在刚开始接触Orchard CMS,对于个性化的网页布局不知道怎么定义,通过google的帮助终于找到比较符合Orchard的二次开发方法的解决方案,就是在Theme定义布局Widgets Layout。需要注意的是,因为要在Theme写C#代码,所以要用Orchard 命令提示创建Theme的解决方案(命令:codegen theme <theme-name> /CreateProject:true)。
当Theme的解决方案方案建立好后我们就可以开始定义自己的Widgets Layout,在这里我以自己网站上首页的一个产品展示Widgets为例子说明(此为新开发没有同步到发布站点),最后实现好的效果如下:
下面开始介绍代码的编写,第一步需要在刚建好的Theme的解决方案里,新建名称为Providers的文件夹,第二步在建好Providers文件里新建ProductsListLayoutForms的类,它必须实现Orchard里的 IFormProvider 接口,这个类主要作用是为Widgets 中HTML DOM的Id,class 提供配置表单,为以后修改class和id提供方便,具体代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using Orchard.DisplayManagement;
- using Orchard.Forms.Services;
- using Orchard.Localization;
- namespace UBOfficeTheme.Providers.Layouts
- {
- public class ProductsListLayoutForms : IFormProvider
- {
- protected dynamic Shape { get; set; }
- public Localizer T { get; set; }
- public ProductsListLayoutForms(IShapeFactory shapeFactory)
- {
- Shape = shapeFactory;
- T = NullLocalizer.Instance;
- }
- public void Describe(DescribeContext context)
- {
- Func<IShapeFactory, object> form =
- shape =>
- {
- var f = Shape.Form(
- Id: "ProductsListLayout",
- _HtmlProperties: Shape.Fieldset(
- Title: T("Html properties"),
- _ListId: Shape.TextBox(
- Id: "culture-id",
- Name: "CultureId",
- Title: T("culture id"),
- Description: T("The id to provide on the culture div element."),
- Classes: new[] { "textMedium", "tokenized" }
- ),
- _ListClass: Shape.TextBox(
- Id: "culture-classes",
- Name: "CultureClasses",
- Title: T("culture classes"),
- Description: T("The class to provide on the culture div element."),
- Classes: new[] { "textMedium", "tokenized" }
- ),
- _CultureTitle: Shape.TextBox(
- Id: "culturetitle-classes",
- Name: "CultureTitleClasses",
- Title: T("culture title classes"),
- Description: T("The class to provide on the culturetitle div element."),
- Classes: new[] { "textMedium", "tokenized" }
- ),
- _ProductsId:Shape.TextBox(
- Id: "products-id",
- Name: "ProductsId",
- Title: T("products id"),
- Description: T("The id to provide on the products div element."),
- Classes: new[] { "textMedium", "tokenized" }
- ),
- _ProductsClass:Shape.TextBox(
- Id: "products-classes",
- Name: "ProductsClasses",
- Title: T("products classes"),
- Description: T("The class to provide on the products div element."),
- Classes: new[] { "textMedium", "tokenized" }
- )
- )
- );
- return f;
- };
- context.Form("ProductsListLayout", form);
- }
- }
- }
第三步需要新建一个ProductsListLayout的类,此类必须实现Orchard里ILayoutProvider接口,此类的作用有两点,第一:为Projections(后面章节有说明)选择布局供时提供布名称和说明,第二:调用构造具体布局的实现,并提供class 和 id传参,具体代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using Orchard.ContentManagement;
- using Orchard.DisplayManagement;
- using Orchard.Localization;
- using Orchard.Projections.Descriptors.Layout;
- using Orchard.Projections.Models;
- using Orchard.Projections.Services;
- namespace UBOfficeTheme.Providers.Layouts
- {
- public class ProductsListLayout : ILayoutProvider
- {
- private readonly IContentManager _contentManager;
- protected dynamic Shape { get; set; }
- public Localizer T { get; set; }
- public ProductsListLayout(IShapeFactory shapeFactory, IContentManager contentManager)
- {
- _contentManager = contentManager;
- Shape = shapeFactory;
- T = NullLocalizer.Instance;
- }
- public void Describe(DescribeLayoutContext describe)
- {
- describe.For("Html", T("Html"), T("Html Layouts"))
- .Element("ProductsList", T("ProductsList"), T("Organizes content items in a ProductsList."),
- DisplayLayout,
- RenderLayout,
- "ProductsListLayout"
- );
- }
- public dynamic RenderLayout(LayoutContext context, IEnumerable<LayoutComponentResult> layoutComponentResults)
- {
- string cultureId = context.State.CultureId;
- string cultureClasses = context.State.CultureClasses;
- string culturetitleClasses = context.State.CultureTitleClasses;
- string productsId = context.State.ProductsId;
- string productsClasses = context.State.ProductsClasses;
- IEnumerable<dynamic> shapes =
- context.LayoutRecord.Display == (int)LayoutRecord.Displays.Content
- ? layoutComponentResults.Select(x => _contentManager.BuildDisplay(x.ContentItem, context.LayoutRecord.DisplayType))
- : layoutComponentResults.Select(x => x.Properties);
- return Shape.ProductsList(
- Id: cultureId,
- Items: shapes,
- pcultureClasses: new[] { cultureClasses },
- pculturetitleClasses: new[] { culturetitleClasses },
- productsClasses: new[] { productsClasses },
- productsId : productsId
- );
- }
- public Func<LayoutContext, LocalizedString> DisplayLayout { get; set; }
- }
- }
第四步新建一个LayoutShapes 此类必须实现Orchard里IDependency接口,此类的作用为本Theme解决方案里的所有自定义布局提供具体实现,定义布局方法是有三点需要注意,第一:在方法前必须要加上 [Shape]的属性,第二点:方法名称必须和ProductsListLayout类中的RenderLayout方法返回语句中Shape调用名称相同。第三点:定义的方法参数除去dynamic Display, TextWriter Output, HtmlHelper Html由Orchard本身框架提供,其余一部由ProductsListLayout类中的RenderLayout方法返回语句中的Shape调用方法传递,一部是自己定义给class使用的字典集合。具体代码如下:
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Web;
- using System.Web.Mvc;
- using Orchard;
- using Orchard.Autoroute.Models;
- using Orchard.ContentManagement;
- using Orchard.DisplayManagement;
- using Orchard.Localization;
- using Orchard.UB.Portal.Models;
- using Orchard.UI.Resources;
- namespace UBOfficeTheme.Providers.Layouts
- {
- public class LayoutShapes : IDependency
- {
- private readonly IWorkContextAccessor _workContextAccessor;
- private readonly IContentManager _contentManager;
- private readonly IOrchardServices _orchardServices;
- public Localizer T { get; set; }
- public LayoutShapes(IOrchardServices orchardServices,
- IWorkContextAccessor workContextAccessor, IContentManager contentManager)
- {
- _workContextAccessor = workContextAccessor;
- T = NullLocalizer.Instance;
- _contentManager = contentManager;
- _orchardServices = orchardServices;
- }
- [Shape]
- public void ProductsList(dynamic Display, TextWriter Output, HtmlHelper Html, string Id,
- IEnumerable<dynamic> Items,
- IEnumerable<string> pcultureClasses,
- IDictionary<string, string> pcultureAttr,
- IEnumerable<string> pculturetitleClasses,
- IDictionary<string, string> pculturetitleAttr,
- IEnumerable<string> productsClasses,
- IDictionary<string, string> productsAttr,
- string productsId)
- {
- if (Items == null) return;
- var items = Items.ToList();
- var itemsCount = items.Count;
- if (itemsCount < 1) return;
- string baseUrl = _workContextAccessor.GetContext().CurrentSite.BaseUrl;
- var cultureDivTag = GetTagBuilder("div", Id, pcultureClasses, pcultureAttr);
- var cultureDivTitleTag = GetTagBuilder("div", string.Empty, pculturetitleClasses, pculturetitleAttr);
- var proddetailDivTag = GetTagBuilder("div", productsId, productsClasses, productsAttr);
- var proddetailUlTag = GetTagBuilder("ul", productsId, productsClasses, productsAttr);
- Output.Write(cultureDivTag.ToString(TagRenderMode.StartTag));
- Output.Write(cultureDivTitleTag.ToString(TagRenderMode.StartTag));
- Output.Write("<h6 class='fl'><strong></strong>新品推荐<span>NEW PRODUCTS</span></h6>");
- Output.Write(string.Format("<a href='{0}/{1}' class='fr'></a>", baseUrl, "executivedesk"));
- Output.Write(cultureDivTitleTag.ToString(TagRenderMode.EndTag));
- Output.Write("<div>");
- Output.Write(proddetailDivTag.ToString(TagRenderMode.StartTag));
- Output.Write("<a href=\"javascript:void(0)\" id=\"prev\" ></a>");
- Output.Write("<div>");
- Output.Write(proddetailUlTag.ToString(TagRenderMode.StartTag));
- for (int i = 0; i < items.Count; i++)
- {
- var pictureField = ((Orchard.ContentManagement.ContentItem)items[i].ContentItem).Parts.SelectMany(p => p.Fields).Where(f => f.Name.Contains("picture")).SingleOrDefault();
- var imglist = ((Orchard.MediaLibrary.Fields.MediaLibraryPickerField)pictureField).MediaParts.OrderBy(c => c.AlternateText).ToList();
- foreach (var item in imglist)
- {
- Output.Write("<li><a href='{2}/{3}'><img src='{0}' alt='优比家具-{1}'/></a></li>", item.MediaUrl, item.Title, baseUrl,item.Caption);
- }
- }
- Output.Write(proddetailUlTag.ToString(TagRenderMode.EndTag));
- Output.Write("</div>");
- Output.Write("<a href=\"javascript:void(0)\" id=\"next\" ></a>");
- Output.Write(proddetailDivTag.ToString(TagRenderMode.EndTag));
- Output.Write(cultureDivTag.ToString(TagRenderMode.EndTag));
- }
- static TagBuilder GetTagBuilder(string tagName, string id, IEnumerable<string> classes, IDictionary<string, string> attributes)
- {
- var tagBuilder = new TagBuilder(tagName);
- tagBuilder.MergeAttributes(attributes, false);
- foreach (var cssClass in classes ?? Enumerable.Empty<string>())
- tagBuilder.AddCssClass(cssClass);
- if (!string.IsNullOrWhiteSpace(id))
- tagBuilder.GenerateId(id);
- return tagBuilder;
- }
- }
- }
到这里代码编写全部完成。下一篇介绍配置。
在Orchard CMS Theme 用代码定义布局Widgets的更多相关文章
- 在Orchard CMS Theme 用代码定义布局Widgets 配置
在上篇中主要详细的叙述了代码的编写,这一篇主要讲解配置.可能有人会有疑问,在上一篇的代码里只有对数据的展示部分的编写,并没有提供数据源.这就是Orchard的强大之处,数据源是通过在后台配置的,那有人 ...
- [Orchard CMS系列] 创建主题(Writing a new theme)
本文需要对Orchard CMS有基本了解. 开启模块 code generation 创建新的主题工程骨架 Codegen theme MyTheme 创建主题样式 src\Orchard.Web\ ...
- Orchard CMS中如何打包不带源码的模块
在Orchard CMS的官网已经提供了文档说明如何打包,但是如果使用它的打包方式,打好的nuget包是带源代码的.如果是为开源系统写模块,不需要关注源代码是否可见.但是如果是用Orchard CMS ...
- SharePoint 2013 图文开发系列之代码定义列表
在SharePoint的开发中,用Visual Studio自定义列表是经常会用到的,因为很多时候,我们并不会手动创建列表,而手动创建列表在测试服务器和正式机之间同步字段,也很麻烦,所以我们经常用代码 ...
- WPF中通过代码定义模板
WPF中可以再XAML中定义模板,也可以通过C#代码定义模板,通过代码可能更清楚的看清其逻辑,而且代码的好处就是可以随时动态的去操作,而在XAML中定义的一般都是静态的. //控件呈现的显示内容1(这 ...
- SharePoint 2013 设置自己定义布局页
在SharePoint中.我们常常须要自己定义登陆页面.错误页面.拒绝訪问等:不知道大家怎样操作,曾经自己常常在原来页面改或者跳转.事实上SharePoint为我们提供了PowerShell命令,来改 ...
- 在 Windows Azure 网站 (WAWS) 上对 Orchard CMS 使用 Azure 缓存
编辑人员注释: 本文章由 Windows Azure 网站团队的项目经理 Sunitha Muthukrishna 撰写. 如果您当前的 OrchardCMS 网站在 Windows Azure 网站 ...
- Orchard CMS -Migration文件更新后数据库不更新的问题 new properties not updating after migrationData migration is not working?
Orchard CMS - new properties not updating after migrationData migration is not working? If your mapp ...
- cucumber java从入门到精通(2)用代码定义步骤
cucumber java从入门到精通(2)用代码定义步骤 上一节里我们定义了feature文件,feature文件就是自然语言描述的用例文件,它有一定的章法,具体的潜规则是: 使用Feature关键 ...
随机推荐
- python基础——2(基本数据类型及运算符)
目录 为何数据要区分类型? 一.数字类型 1.整型int 2.浮点型float 二.字符串str 三.列表类型list 四.字典类型 五.布尔类型 运算符的介绍 一.算术运算符 二.比较运算符 三.赋 ...
- angular中的http拦截器Interceptors
在angularJs中增加了一个对全局的http请求统一做出处理的api--interceptors Interceptors 有两个处理时机,分别是: 其它程序代码执行 HTTP 请求之后,在实际从 ...
- spring源码深度解析—Spring的整体架构和环境搭建
概述 Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于2003 年兴起的一个轻量级的Java 开发框 ...
- 一个jboss启动shell脚本
脚本1: #!/bin/sh # paulo@evencom.com.br #JBOSS_HOME JBOSS_HOME="/opt/app/jboss-eap-6.3" JAVA ...
- Leetcode 301.删除无效的括号
删除无效的括号 删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果. 说明: 输入可能包含了除 ( 和 ) 以外的字符. 示例 1: 输入: "()())()" 输出 ...
- 【ITOO 4】WCF中,分布式事务处理
导读:事务可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源.通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠.在项目中,就有 ...
- 【组合数模板】HDU 6114 Chess
http://acm.hdu.edu.cn/showproblem.php?pid=6114 [思路] 就是求C(m,n) [板] #include<iostream> #include& ...
- bzoj1709 [Usaco2007 Oct]Super Paintball超级弹珠 暴力
[Usaco2007 Oct]Super Paintball超级弹珠 Description 奶牛们最近从著名的奶牛玩具制造商Tycow那里,买了一套仿真版彩弹游戏设备(类乎于真人版CS). Bess ...
- msp430入门编程47
msp430中C语言的人机交互--菜单退出 msp430入门编程 msp430入门学习
- js面试题总结
1.typeof和Object.prototype.toString typeof是js里面判断变量类型的一种方法,但这种方法没有Object.prototype.toString准确,前者有6种判断 ...