A shape is a dynamic data model.
_shape_是动态数据模型。
The purpose of a shape is to replace the static view model of ASP.NET MVC by using a model
形状的目的是使用模型替换ASP.NET MVC的静态视图模型
that can be updated at runtime -- that is, by using a dynamic shape.
可以在运行时更新 - 也就是说,通过使用动态形状。
You can think of shapes as the blobs of data that get handed to templates for rendering.
您可以将形状视为传递给模板进行渲染的数据块。
This article introduces the concept of shapes and explains how to work with them.
本文介绍了形状的概念,并解释了如何使用它们。
It's intended for module and theme developers who have at least a basic understanding of Orchard modules.
它适用于至少对Orchard模块有基本了解的模块和主题开发人员。
For information about creating modules, see the Getting Started with Modules course.
有关创建模块的信息,请参阅[模块入门课程](模块入门)。
For information about dynamic objects, see Creating and Using Dynamic Objects.
有关动态对象的信息,请参阅[创建和使用动态对象](http://msdn.microsoft.com/en-us/library/ee461504.aspx)。
Introducing Shapes
介绍形状
Shapes are dynamic data models that use shape templates to make the data visible to the user in the way you want.
形状是动态数据模型,它使用形状模板以您希望的方式使用户可以看到数据。
Shape templates are fragments of markup for rendering shapes.
形状模板是用于渲染形状的标记片段。
Examples of shapes include menus, menu items, content items, documents, and messages.
形状的示例包括菜单,菜单项,内容项,文档和消息。
A shape is a data model object that derives from the Orchard.DisplayManagement.Shapes.Shape
class.
形状是一个数据模型对象,它派生自Orchard.DisplayManagement.Shapes.Shape
类。
The Shape
class is never instantiated. Instead, shapes are created at run time by a shape factory.
Shape
类永远不会被实例化。而是由形状工厂在运行时创建形状。
The default shape factory is Orchard.DisplayManagement.Implementation.DefaultShapeFactory
.
默认的形状工厂是Orchard.DisplayManagement.Implementation.DefaultShapeFactory
。
The shapes created by the shape factory are dynamic objects.
形状工厂创建的形状是动态对象。
Note`
注意`
`Dynamic objects are new to the .NET Framework 4.
As a dynamic object, a shape exposes its members at run time instead of at compile time.
作为动态对象,形状在运行时而不是在编译时公开其成员。
By contrast, an ASP.NET MVC model object is a static object that's defined at compile time.
相比之下,ASP.NET MVC模型对象是在编译时定义的静态对象。
Information about the shape is contained in the ShapeMetadata
property of the shape itself.
有关形状的信息包含在形状本身的ShapeMetadata
属性中。
This information includes the shape's type, display type, position, prefix, wrappers, alternates, child content, and a WasExecuted
Boolean value.
此信息包括形状的类型,显示类型,位置,前缀,包装,替代,子内容和WasExecuted
布尔值。
You can access the shape's metadata as shown in the following example:
您可以访问形状的元数据,如以下示例所示:
var shapeType = shapeName.Metadata.Type;
After the shape object is created, the shape is rendered with the help of a shape template.
创建形状对象后,将在形状模板的帮助下渲染形状。
A shape template is a piece of HTML markup (partial view) that is responsible for displaying the shape.
形状模板是一个HTML标记(局部视图),负责显示形状。
Alternatively, you can use a shape attribute (Orchard.DisplayManagement.ShapeAttribute
)
或者,您可以使用shape属性(Orchard.DisplayManagement.ShapeAttribute
)
that enables you to write code that creates and displays the shape without using a template.
这使您可以编写创建和显示形状的代码,而无需使用模板。
Creating Shapes
创建形状
For module developers, the most common need for shapes is to transport data from a driver to a template for rendering.
对于模块开发人员,形状最常见的需求是将数据从驱动程序传输到模板以进行渲染。
A driver derives from the Orchard.ContentManagement.Drivers.ContentPartDriver
class
驱动程序派生自Orchard.ContentManagement.Drivers.ContentPartDriver
类
and typically overrides that class's Display
and Editor
methods.
并且通常会覆盖该类的“Display”和“Editor”方法。
The Display
and Editor
methods return a ContentShapeResult
object, which is analogous to
Display
和Editor
方法返回一个ContentShapeResult
对象,类似于
the ActionResult
object returned by action methods in ASP.NET MVC.
ASP.NET MVC中的操作方法返回的ActionResult
对象。
The ContentShape
method helps you create the shape and return it in a ContentShapeResult
object.
ContentShape
方法可以帮助您创建形状并将其返回到ContentShapeResult
对象中。
Although the ContentShape
method is overloaded, the most typical use is to pass it two parameters -- the shape type and a dynamic function expression that defines the shape.
虽然ContentShape
方法是重载的,但最典型的用法是传递两个参数 - 形状类型和定义形状的动态函数表达式。
The shape type names the shape and binds the shape to the template that will be used to render it.
形状类型命名形状并将形状绑定到将用于渲染它的模板。
The naming conventions for shape types are discussed later in
形状类型的命名约定将在后面讨论
[命名形状和模板](访问和渲染形状#NamingShapesandTemplates)。
The function expression can be described best by using an example.
通过使用示例可以最好地描述函数表达式。
The following example shows a driver's Display
method that returns a shape result,
以下示例显示了一个返回形状结果的驱动程序Display
方法,
which will be used to display a Map
part.
这将用于显示“地图”部分。
protected override DriverResult Display(
MapPart part, string displayType, dynamic shapeHelper)
{
return ContentShape("Parts_Map",
() => shapeHelper.Parts_Map(
Longitude: part.Longitude,
Latitude: part.Latitude));
}
The expression uses a dynamic object (shapeHelper
) to define a Parts_Map
shape and its attributes.
该表达式使用动态对象(shapeHelper
)来定义Parts_Map
形状及其属性。
The expression adds a Longitude
property to the shape and sets it equal to the part's Longitude
property.
The expression also adds a Latitude
property to the shape and sets it equal to the part's Latitude
property.
该表达式还为形状添加了“Latitude”属性,并将其设置为等于部分的“Latitude”属性。
The ContentShape
method creates the results object that is returned by the Display
method.
ContentShape
方法创建Display
方法返回的结果对象。
The following example shows the entire driver class that sends a shape result to a template either
以下示例显示了将形状结果发送到模板的整个驱动程序类
to be displayed or edited in a Map
part. The Display
method is used to display the map.
在Map
部分显示或编辑。 Display
方法用于显示地图。
The Editor
method marked "GET" is used to display the shape result in editing view for user input.
标记为“GET”的Editor
方法用于在编辑视图中显示用户输入的形状结果。
The Editor
method marked "POST" is used to redisplay the editor view using the values provided by the user.
标有“POST”的Editor
方法用于使用用户提供的值重新显示编辑器视图。
These methods use different overloads of the Editor
method.
这些方法使用Editor
方法的不同重载。
using Maps.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
namespace Maps.Drivers
{
public class MapPartDriver : ContentPartDriver<MapPart>
{
protected override DriverResult Display(
MapPart part, string displayType, dynamic shapeHelper)
{
return ContentShape("Parts_Map",
() => shapeHelper.Parts_Map(
Longitude: part.Longitude,
Latitude: part.Latitude));
}
//GET
protected override DriverResult Editor(
MapPart part, dynamic shapeHelper)
{
return ContentShape("Parts_Map_Edit",
() => shapeHelper.EditorTemplate(
TemplateName: "Parts/Map",
Model: part));
}
//POST
protected override DriverResult Editor(
MapPart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
}
The Editor
method marked "GET" uses the ContentShape
method to create a shape for an editor template.
标记为“GET”的Editor
方法使用ContentShape
方法为编辑器模板创建形状。
In this case, the type name is Parts_Map_Edit
and the shapeHelper
object creates an EditorTemplate
shape.
在这种情况下,类型名称是Parts_Map_Edit
,shapeHelper
对象创建EditorTemplate
形状。
This is a special shape that has a TemplateName
property and a Model
property.
这是一个特殊形状,具有TemplateName
属性和Model
属性。
The TemplateName
property takes a partial path to the template.
TemplateName
属性采用模板的部分路径。
In this case, "Parts/Map"
causes Orchard to look for a template in your module at the following path:
在这种情况下,Parts / Map
使Orchard在以下路径中查找模块中的模板:
Views/EditorTemplates/Parts/Map.cshtml
The Model
property takes the name of the part's model file, but without the file-name extension.
Model
属性采用Part的模型文件的名称,但没有文件扩展名。
Naming Shapes and Templates
命名形状和模板
As noted, the name given to a shape type binds the shape to the template that will be used to render the shape.
如上所述,赋予形状类型的名称将形状绑定到将用于渲染形状的模板。
For example, suppose you create a part named Map
that displays a map for the specified longitude and latitude.
例如,假设您创建了一个名为“Map”的part,该part显示指定经度和纬度的地图。
The name of the shape type might be Parts_Map
. By convention, all part shapes begin with Parts_
followed by the name of the part (in this case Map
). Given this name (Parts_Map
), Orchard looks for a template in your module at the following path:
形状类型的名称可能是Parts_Map
。按照惯例,所有part形状都以Parts_
开头,后跟part名称(在本例中为Map
)。给定此名称(Parts_Map
),Orchard在以下路径中查找模块中的模板:
views/parts/Map.cshtml
The following table summarizes the conventions that are used to name shape types and templates.
下表总结了用于命名形状类型和模板的约定。
Applied To | Shape Naming Convention | Shape Type Example | Template Example
---------------------- | ------------------------------------------------------ | -----------------------------------------------| --------------------------------------------
Content shapes | Content__[ContentType]
| Content__BlogPost
| Content-BlogPost
Content shapes | Content__[Id]
| Content__42
| Content-42
Content shapes | Content__[DisplayType]
| Content__Summary
| Content.Summary
Content shapes | Content_[DisplayType]__[ContentType]
| Content_Summary__BlogPost
| Content-BlogPost.Summary
Content shapes | Content_[DisplayType]__[Id]
| Content_Summary__42
| Content-42.Summary
Content.Edit shapes | Content_Edit__[DisplayType]
| Content_Edit__Page
| Content-Page.Edit
Content Part templates | [ShapeType]__[Id]
| Parts_Common_Metadata__42
| Parts/Common.Metadata-42
Content Part templates | [ShapeType]__[ContentType]
| Parts_Common_Metadata__BlogPost
| Parts/Common.Metadata-BlogPost
Field templates | [ShapeType]__[FieldName]
| Fields_Common_Text__Teaser
| Fields/Common.Text-Teaser
Field templates | [ShapeType]__[PartName]
| Fields_Common_Text__TeaserPart
| Fileds/Common.Text-TeaserPart
Field templates | [ShapeType]__[ContentType]__[PartName]
| Fields_Common_Text__Blog__TeaserPart
| Fields/Common.Text-Blog-TeaserPart
Field templates | [ShapeType]__[PartName]__[FieldName]
| Fields_Common_Text__TeaserPart__Teaser
| Fields/Common.Text-TeaserPart-Teaser
Field templates | [ShapeType]__[ContentType]__[FieldName]
| Fields_Common_Text__Blog__Teaser
| Fields/Common.Text-Blog-Teaser
Field templates | [ShapeType]__[ContentType]__[PartName]__[FieldName]
| Fields_Common_Text__Blog__TeaserPart__Teaser
| Fields/Common.Text-Blog-TeaserPart-Teaser
LocalMenu | LocalMenu__[MenuName]
| LocalMenu__main
| LocalMenu-main
LocalMenuItem | LocalMenuItem__[MenuName]
| LocalMenuItem__main
| LocalMenuItem-main
Menu | Menu__[MenuName]
| Menu__main
| Menu-main
MenuItem | MenuItem__[MenuName]
| MenuItem__main
| MenuItem-main
Resource | Resource__[FileName]
| Resource__flower.gif
| Resource-flower.gif
Style | Style__[FileName]
| Style__site.css
| Style-site.css
Widget | Widget__[ContentType]
| Widget__HtmlWidget
| Widget-HtmlWidget
Widget | Widget__[ZoneName]
| Widget__AsideSecond
| Widget-AsideSecond
Zone | Zone__[ZoneName]
| Zone__AsideSecond
| Zone-AsideSecond
You should put your templates in the project according to the following rules:
您应该根据以下规则将模板放入项目中:
-
Content item shape templates are in the
Views/Items
folder. -
内容项形状模板位于
Views / Items
文件夹中。 * -
Parts_
shape templates are in theViews/Parts
folder. -
Parts_
形状模板位于Views / Parts
文件夹中。 * -
Fields_
shape templates are in theViews/Fields
folder. -
Fields_
形状模板位于Views / Fields
文件夹中。 * -
The
EditorTemplate
shape templates are in theViews/EditorTemplates/<templatename>
folder. -
EditorTemplate
形状模板位于Views / EditorTemplates / <templatename>
文件夹中。 *
For example, an EditorTemplate
with a template name of Parts/Routable.RoutePart
has its template at Views/EditorTemplates/Parts/Routable.RoutePart.cshtml
.
例如,模板名称为“Parts/Routable.RoutePart”的EditorTemplate
的模板位于Views/EditorTemplates/Parts/Routable.RoutePart.cshtml
。
-
All other shape templates are in the
Views
folder. -
所有其他形状模板都在
Views
文件夹中。 *
Note
!注意
The template extension can be any extension supported by an active view engine, such as `.cshtml`, `.vbhtml`, or `.ascx`.
<font color=#0099ff size=4 face="黑体">模板扩展可以是活动视图引擎支持的任何扩展,例如`.cshtml`,`.vbhtml`或`.ascx`。</font>
From Template File Name to Shape Name
从模板文件名到形状名称
More generally, the rules to map from a template file name to the corresponding shape name are the following:
更一般地,从模板文件名映射到相应形状名称的规则如下:
-
Dot (
.
) and backslash (\
) change to underscore (_
). -
Dot(
.
)和反斜杠(\
)变为下划线(_
)。 *
Note that this does not mean that an example.cshtml
file in a myviews
subdirectory of Views
is equivalent to a myviews
example.chtmlfile in
Views_.
请注意,这并不意味着Views
的myviews
子目录中的example.cshtml
文件等同于Views_中的
myviewsexample.chtml
文件。(译者注:不等于 Views_myviews_example.cshtml?)
The shape templates must still be in the expected directory (see above).
形状模板仍必须位于预期目录中(参见上文)。
-
Hyphen (
-
) changes to a double underscore (__
). -
连字符(
-
)变为双下划线(__
)。 *
For example, Views/Hello.World.cshtml
will be used to render a shape named Hello_World
,
例如,Views / Hello.World.cshtml
将用于渲染名为Hello_World
的形状,
and Views/Hello.World-85.cshtml
will be used to render a shape named Hello_World__85
.
和Views / Hello.World-85.cshtml
将用于渲染名为Hello_World__85
的形状。
Alternate Shape Rendering
part形状渲染
As noted, an HTML widget in the AsideSecond
zone (for example) could be rendered by a widget.cshtml
template, by a widget-htmlwidget.cshtml
template,
如上所述,AsideSecond
区域中的HTML小部件(例如)可以通过widget.cshtml
模板,widget-htmlwidget.cshtml
模板呈现,
or by a widget-asidesecond.cshtml
if they exist in the current theme.
或者通过widget-asidesecond.cshtml
,如果它们存在于当前主题中。
When various possibilities exist to render the same content,
当存在各种可能性来呈现相同的内容时,
these are referred to as alternates of the shape,
这些被称为形状的_alternates_,
and they enable rich template overriding scenarios.
并且它们启用了丰富的模板覆盖方案。
Alternates form a group that corresponds to the same shape if they differ only by a double-underscore suffix.
如果它们仅由双下划线后缀不同,则part形成对应于相同形状的组。
For example, Hello_World
, Hello_World__85
, and Hello_World__DarkBlue
are an alternate group
例如,Hello_World
,Hello_World__85
和Hello_World__DarkBlue
是备用组
for a Hello_World
shape. Hello_World_Summary
, conversely, does not belong to that group
为Hello_World
形状。相反,Hello_World_Summary
不属于该组
and would correspond to a Hello_World_Shape
shape, not to a Hello_World
shape.
并且对应于“Hello_World_Shape”形状,而不是“Hello_World”形状。
(Notice the difference between "__
" and "_
".)
(注意“__”和“_”之间的区别。)
Which Alternate Will Be Rendered?
哪些part会被渲染?
Even if it has alternates, a shape is always created with the base name, such as Hello_World
.
即使它具有alternates,也始终使用基本名称创建形状,例如“Hello_World”。
Alternates give additional template name options to the theme developer beyond the default
part为主题开发人员提供超出默认值的其他模板名称选项
(such as hello.world.cshtml
).
(例如hello.world.cshtml
)。
The system will choose the most specialized template available among the alternates,
系统将选择part品中最专业的模板,
so hello.world-orange.cshtml
will be preferred to hello.world.cshtml
if it exists.
所以hello.world-orange.cshtml
将优先于hello.world.cshtml
(如果存在)。
Built-In Content Item Alternates
内置内容项part
The table above shows possible template names for content items.
上表显示了内容项的可能模板名称。
It should now be clear that the shape name is built from Content
and the display type (for example Content_Summary
).
现在应该很清楚,形状名称是由Content
和显示类型(例如Content_Summary
)构建的。
The system also automatically adds the content type and the content ID as alternates
系统还会自动添加内容类型和内容ID作为part
(for example Content_Summary__Page
and Content_Summary__42
).
(例如Content_Summary__Page
和Content_Summary__42
)。
For more information about how to use alternates, see Alternates.
有关如何使用part项的更多信息,请参阅[part](part)。
Rendering Shapes Using Templates
使用模板渲染形状
A shape template is a fragment of markup that is used to render the shape.
形状模板是用于渲染形状的标记片段。
The default view engine in Orchard is the Razor view engine.
Orchard中的默认视图引擎是Razor视图引擎。
Therefore, shape templates use Razor syntax by default.
因此,形状模板默认使用Razor语法。
For an introduction to Razor syntax, see Template File Syntax Guide.
有关Razor语法的介绍,请参阅[模板文件语法指南](模板文件语法指南)。
The following example shows a template for displaying a Map
part as an image.
以下示例显示了用于将“Map”部分显示为图像的模板。
<img alt="Location" border="1" src="http://maps.google.com/maps/api/staticmap?
&zoom=14
&size=256x256
&maptype=satellite&markers=color:blue|@Model.Latitude,@Model.Longitude
&sensor=false" />
This example shows an img
element in which the src
attribute contains a URL and a set of parameters passed as query-string values.
这个例子显示了一个img
元素,其中src
属性包含一个URL和一组作为查询字符串值传递的参数。
In this query string, @Model
represents the shape that was passed into the template.
在此查询字符串中,“@Model”表示传递给模板的形状。
Therefore, @Model.Latitude
is the Latitude
property of the shape,
因此,@Model.Latitude
是形状的'Latitude`属性,
and @Model.Longitude
is the Longitude
property of the shape.
和@Model.Longitude
是形状的“经度”属性。
The following example shows the template for the editor.
以下示例显示了编辑器的模板。
This template enables the user to enter values for the latitude and longitude.
此模板允许用户输入纬度和经度的值。
@model Maps.Models.MapPart
<fieldset>
<legend>Map Fields</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Longitude)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Latitude)
@Html.ValidationMessageFor(model => model.Latitude)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Longitude)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Longitude)
@Html.ValidationMessageFor(model => model.Longitude)
</div>
</fieldset>
The @Html.LabelFor
expressions create labels using the name of the shape properties.
@Html.LabelFor
表达式使用形状属性的名称创建标签。
The @Html.TextBoxFor
expressions create text boxes where users enter values for the shape properties.
@Html.TextBoxFor
表达式创建文本框,用户可在其中输入形状属性的值。
The @Html.ValidationMessageFor
expressions create messages that are displayed if users enter an invalid value.
@ Html.ValidationMessageFor
表达式创建在用户输入无效值时显示的消息。
Wrappers
包装
Wrappers let you customize the rendering of a shape by adding markup around the shape.
Wrappers允许您通过在形状周围添加标记来自定义形状的渲染。
For example, Document.cshtml
is a wrapper for the Layout
shape, because it specifies the markup code that surrounds the Layout
shape.
例如,Document.cshtml
是Layout
形状的包装器,因为它指定了围绕Layout
形状的标记代码。
For more information about the relationship between Document
and Layout
,
有关“Document”和“Layout”之间关系的更多信息,
see Template File Syntax Guide.
请参阅[模板文件语法指南](模板文件语法指南)。
Typically, you add a wrapper file to the Views
folder of your theme.
通常,您将包装器文件添加到主题的Views
文件夹中。
For example, to add a wrapper for Widget
, you add a Widget.Wrapper.cshtml
file to the Views
folder of your theme.
例如,要为Widget
添加一个包装器,可以将Widget.Wrapper.cshtml
文件添加到主题的Views
文件夹中。
If you enable the Shape Tracing feature, you'll see the available wrapper names for a shape.
如果启用形状跟踪功能,您将看到形状的可用包装名称。
You can also specify a wrapper in the Placement.info
file.
您还可以在Placement.info
文件中指定包装器。
For more information about how to specify a wrapper,
有关如何指定包装器的更多信息,
see Understanding the Placement.info File.
请参阅[了解Placement.info文件](了解-position-info)。
Creating a Shape Method
创建形状方法
Another way to create and render a shape is to create a method that both defines and renders the shape.
创建和渲染形状的另一种方法是创建一个定义和渲染形状的方法。
The method must be marked with the Shape
attribute (the Orchard.DisplayManagement.ShapeAttribute
class).
该方法必须使用Shape
属性(Orchard.DisplayManagement.ShapeAttribute
类)进行标记。
The method returns an IHtmlString
object instead of using a template;
该方法返回一个IHtmlString
对象,而不是使用模板;
the returned object contains the markup that renders the shape.
返回的对象包含呈现形状的标记。
The following example shows the DateTimeRelative
shape.
以下示例显示了DateTimeRelative
形状。
This shape takes a DateTime
value in the past and returns a string that relates the value to the current time.
此形状过去采用“DateTime”值,并返回一个字符串,该值将值与当前时间相关联。
public class DateTimeShapes : IDependency {
private readonly IClock _clock;
public DateTimeShapes(IClock clock) {
_clock = clock;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
[Shape]
public IHtmlString DateTimeRelative(HtmlHelper Html, DateTime dateTimeUtc) {
var time = _clock.UtcNow - dateTimeUtc;
if (time.TotalDays > 7)
return Html.DateTime(dateTimeUtc, T("'on' MMM d yyyy 'at' h:mm tt"));
if (time.TotalHours > 24)
return T.Plural("1 day ago", "{0} days ago", time.Days);
if (time.TotalMinutes > 60)
return T.Plural("1 hour ago", "{0} hours ago", time.Hours);
if (time.TotalSeconds > 60)
return T.Plural("1 minute ago", "{0} minutes ago", time.Minutes);
if (time.TotalSeconds > 10)
return T.Plural("1 second ago", "{0} seconds ago", time.Seconds);
return T("a moment ago");
}
}