zoukankan      html  css  js  c++  java
  • 在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;
            }
        }
    }
    

     到这里代码编写全部完成。下一篇介绍配置。

        

  • 相关阅读:
    虚拟机与宿主机网络配置——可互通可上网
    CentOs7下安装Redis
    RabbitMQ使用(下)
    RabbitMQ使用(上)
    定制属于你自己的ViewEngine(一套逻辑多套UI)
    JWT With NetCore WebApi
    day02
    day01
    4、python与MongoDB交互
    3、MongoDB的详细查找
  • 原文地址:https://www.cnblogs.com/ww5552031/p/3470835.html
Copyright © 2011-2022 走看看