Skip to content

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

DisplayEditor方法返回一个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

形状类型的命名约定将在后面讨论

Naming Shapes and Templates.

[命名形状和模板](访问和渲染形状#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_EditshapeHelper对象创建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 the Views/Parts folder.

  • Parts_形状模板位于Views / Parts文件夹中。 *

  • Fields_ shape templates are in the Views/Fields folder.

  • Fields_形状模板位于Views / Fields文件夹中。 *

  • The EditorTemplate shape templates are in the Views/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 myviewsexample.chtmlfile inViews_.

请注意,这并不意味着Viewsmyviews子目录中的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_WorldHello_World__85Hello_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__PageContent_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.

@ H​​tml.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.cshtmlLayout形状的包装器,因为它指定了围绕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");
    }
}