七、制作主题(五) Alternates

Alternates是shape选项的变种,在特殊情况下为了你能在主题中实现定制呈现shape,使用Alternates,你能基于内容的类型重写用于呈现内容的模板。例如:你能使用alternates为主页应用一个layout文件,为subpages应用另一个layout文件,或者你能当tags在page中时用alternates以一种方式呈现tags,在blog post中时用另外一种方式呈现。

Orchard framework使用一个命名约定决定是否用一个模板呈现内容。命名约定使你添加文件能自动地使用,不需要修改任何代码。

 

Naming Convention for Alternates

Alternate shapes使用基于shape的名称紧跟一个双下划线(__)和具体alternate shape的结束符,例如:Parts_Tags_ShowTags shape能有Parts_Tags_ShowTags__BlogPost andParts_Tags_ShowTags__Page这样的Alternate shapes,当shape被使用时候选名称的一部分在双下划线之后,如当前的内容类型。

 

Mapping a Template File to an Alternate

要创建对应shape name到一个模板文件的映射,你必须根据下面约定命名模板:

 

  • 转换shape名称中的下划线为模板名称中 点(.)或反斜线符号(\)。反斜线代表子文件夹中的模板。
  • 转换shape名称中的双下划线(__)为字符连接符(-).
  • 对于shape name中显示的类型值 替换 模板名称结尾的点(.)之后的类型名称。如Content-BlogPost.Summary。

所有alternates模板必须在Views文件夹中,Views文件夹能在主题 或模块中。下表展示为不同类型的模板使用哪个Views子文件夹

Shape type Template Folder
Content item Views\Items
Parts Views\Parts
Fields Views\Fields
EditorTemplate Views\EditorTemplates\[template type folder] (For example, an EditorTemplate for a part is located at Views\EditorTemplates\Parts.)
All other Views

 

例如:为Tags part创建候选模板,你能将模板放入MyTheme\Views\Parts文件夹中。不过,因为下划线会被转换为点或反斜线,你也能在Views中创建模板和添加part. 作为名称的开始。在Views\Parts\Tags.ShowTags-BlogPost.cshtmlViews\Parts.Tags.ShowTags-BlogPost.cshtml中的模板会被映射到shape 名为 Parts_Tags_ShowTags__BlogPost。

如果Orchard framework不能定位有预期名称的候选模板,会为那个shape使用默认的模板。

Orchard framework自动创建许多候选,你能在程序中使用。可是,你也能为这些候选shapes创建模板。创建候选的模式如下面所示:括号中为匹配模板的例子

For Contentshapes:

  • Content__[DisplayType]. (Example template: Content.Summary)
  • Content__[ContentType]. (Example template: Content-BlogPost)
  • Content__[Id]. (Example template: Content-42)
  • Content[DisplayType]__[ContentType]_. (Example template: Content-BlogPost.Summary)
  • Content[DisplayType]__[Id]_. (Example template: Content-42.Summary)

For Zoneshapes:

  • Zone__[ZoneName]. (Example template: Zone-SideBar)

For menu and menu item shapes:

  • Menu__[MenuName]. (Example template: Menu-main)
  • MenuItem__[MenuName]. (Example template: MenuItem-main)

For local menu and local menu item shapes:

  • LocalMenu__[MenuName]. (Example template: LocalMenu-main)
  • LocalMenuItem__[MenuName]. (Example template: LocalMenuItem-main)

For styles and resources:

  • Style__[FileName]
  • Resource__[FileName]

For widget shapes:

  • Widget__[ZoneName]. (Example template: Widget-SideBar)
  • Widget__[ContentType]. (Example template: Widget-BlogArchive)

For fields:

  • [ShapeType__FieldName]. (Example template: Fields\Common.Text-Teaser)
  • [ShapeType__PartName]. (Example template: Fields\Common.Text-TeaserPart)
  • [ShapeType]__[ContentType]__[PartName]. (Example template: Fields\Common.Text-Blog-TeaserPart)
  • [ShapeType]__[PartName]__[FieldName]. (Example template: Fields\Common.Text-TeaserPart-Teaser)
  • [ShapeType]__[ContentType]__[FieldName]. (Example template: Fields\Common.Text-Blog-Teaser)
  • [ShapeType]__[ContentType]__[PartName]__[FieldName]. (Example template:Fields\Common.Text-Blog-TeaserPart-Teaser)

For content parts:

  • [ShapeType]__[Id]. (Example template: Parts\Common.Metadata-42)
  • [ShapeType]__[ContentType]. (Example template: Parts\Common.Metadata-BlogPost)

URL and Widget Alternates

URL Alternates模块使你能为特殊的URLs创建模板,Widget Alternates使你能在具体的zones中为某个类型的widgets创建额外的候选widget,你必须先启用URL Alternates and Widget Alternate模块的功能,当启用后候选shape会基于URL或zone被创建,这些URL候选是用上面定义的alternate模式组合。

例如:the URL /my-blog/post-1 有关于MenuItem对象的候选,使用下面这样的模板名称:

MenuItem-main
MenuItem-main-url-my-blog
MenuItem-main-url-my-blog-post-1

For the homepage, the following alternate is available:

MenuItem-main-url-homepage

使用这个模块,能添加URL-specific alternates到Layout shape,如下面的:

Layout-url-homepage.为网站的about页添加一个具体的layout:在Themes/ThemeName/Views创建一个名为Layout-url-About.cshtml的新Layout,当访问/About时将会使用。

能从Gallery下载Orchard Designer Tools并启用。

Explicitly Designating an Alternate Template

除了使用自动生成的alternates,你能手动创建一个具体的alternate。在placement.info文件中,能为一个内容类型指定哪个alternates可用。例如:要为呈现blog posts的tags指定一个不同的模板( Parts_Tags_ShowTags_BlogPost作标识),你能修改Orchard.Tags模块的placement.info文件为包含匹配BlogPost类型的元素,下面是修改的示例:

<Placement>
    <Place Parts_Tags_Edit="Content:7"/>
    <Match ContentType="BlogPost">
        <Place Parts_Tags_ShowTags="Header:after.7;Alternate=ShowTags_BlogPost"/>
    </Match>  
    <Match DisplayType="Detail">
        <Place Parts_Tags_ShowTags="Header:after.7"/>
    </Match>
    <Match DisplayType="Summary">
        <Place Parts_Tags_ShowTags="Header:after.7"/>
    </Match>
</Placement>

 

匹配元素的排序是重要的,仅第一个匹配的元素会被使用。在这个例子中,把BlogPost 元素放在Detail and Summary 下面, ShowTags_BlogPost将不会被使用,甚至关于BlogPost items,因为前面的元素匹配  这个item。

Adding Alternates Through Code

除了上面描述的添加alternates的方法外,你能通过代码添加alternates。要通过指明alternate需要创建一个

实现IShapeTableProvider接口的类,然后,为需要alternate的每种类型的shape的OnDisplaying添加处理程序,为ShapeTableBuilder类中的Describe方法指定shape name的参数,处理程序内,添加当alternate使用时需要指定的所有逻辑。下面示例首先展示了为名为Content的shape如何指定一个alternate,但仅当用户在首页时, 它也展示了名为Parts_Tags_ShowTags的shape如何指定一个alternate,当DisplayType是Summary时,

using Orchard;
using Orchard.ContentManagement;
using Orchard.DisplayManagement.Descriptors;

namespace MyTheme.ShapeProviders
{
    public class ExampleShapeProvider : IShapeTableProvider
    {
        private readonly IWorkContextAccessor _workContextAccessor;

        public ExampleShapeProvider(IWorkContextAccessor workContextAccessor)
        {
            _workContextAccessor = workContextAccessor;
        }

        public void Discover(ShapeTableBuilder builder)
        {
            builder.Describe("Content")
                .OnDisplaying(displaying =>
                {
                    if (displaying.ShapeMetadata.DisplayType == "Detail")
                    {
                        ContentItem contentItem = displaying.Shape.ContentItem;
                        if (_workContextAccessor.GetContext().CurrentSite.HomePage
                            .EndsWith(';' + contentItem.Id.ToString())) {

                            displaying.ShapeMetadata.Alternates
                                .Add("Content__HomePage");
                        }
                    }
                });

            builder.Describe("Parts_Tags_ShowTags")
                .OnDisplaying(displaying =>
                {
                    if (displaying.ShapeMetadata.DisplayType == "Summary")
                    {
                        displaying.ShapeMetadata.Alternates
                            .Add("Tags_ShowTags_Summary");
                    }
                });
        }
    }
}
posted @ 2012-03-23 16:16  commanderss  阅读(612)  评论(0编辑  收藏  举报