七、制作主题(五) 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.cshtml 或 Views\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-mainMenuItem-main-url-my-blogMenuItem-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");
}
});
}
}
}

浙公网安备 33010602011771号