开发元件

创建一个元件

元件是一个可重用的逻辑单元,包含逻辑或者UI,他可以附加到内容类型上面。比如,Orchard原生提供了Route元件,使得我们可以将内容项关联到一个特定的URL,还提供了Tag元件,使得内容项具有标签功能。

在这篇文档中,我们会创建一个自定义地图的元件,通过配置经度和纬度,生成一副地图。

首先,我们先创建一个"Maps"模块(请先熟悉上一篇文章,学习如何创建模块):

我们在控制台中,输入下面的命令"codegen module Maps /IncludeInSolution:true" ,创建Map模块,"IncludeInSolution"开关,表示创建的模块,是否自动加入当前解决方案中。

orchard> codegen module Maps /IncludeInSolution:true

Creating module Maps

Module Maps created successfully

执行指令以后,Visual Studio会提示重新加载解决方案:

我们会看到,Maps模块已经加载到解决方案中了。

注意:使用命令,向解决方案中添加了内容后,最好重新编译解决方案,否则可能会出现未知问题,比如,如果没有重新编译,后面使用数据迁移命令后,得到的是一个空的数据迁移文件

编辑Maps模块根目录下面的Module.txt文件(这个文件,记录的该模块的说明信息,比如名称、作者、版本、依赖的特性等等):

Name: Maps

AntiForgery: enabled

Author: The Orchard Team

Website: http://orchardproject.net

Version: 1.0.0

OrchardVersion: 1.0.0

Description: Adds a map image to content items, based on longitude and latitude.

Features:

Maps:

Description: Adds a map image to content items, based on longitude and latitude.

Category: Geolocation

好了,让我们开始创建元件。首先,我们要创建一个类,来持久化元件的数据:

在Models文件夹中,我们创建MapRecord.cs和MapPart.cs两个文件,MapRecord是用于元件的数据持久化,MapPart使用MapRecord,实现了数据存储:

using System.ComponentModel.DataAnnotations;

using Orchard.ContentManagement;

using Orchard.ContentManagement.Records;

 

namespace Maps.Models

{

public class MapRecord : ContentPartRecord

{

public virtual double Latitude { get; set; }

public virtual double Longitude { get; set; }

}

 

public class MapPart : ContentPart<MapRecord>

{

[Required]

public double Latitude

{

get { return Retrieve(r => r.Latitude); }

set { Store(r => r.Latitude, value); }

}

 

[Required]

public double Longitude

{

get { return Retrieve(r => r.Longitude); }

set { Store(r => r.Longitude, value); }

}

}

}

 

接下来,我们创建Maps模块的数据迁移文件。这个文件用于MapRecord和数据库的映射(ORM中的概率,请自学)。同时,这个文件还包含了模块的版本更新内容和初始化内容。

我们通过命令"codegen datamigration Maps"来创建数据迁移文件:

orchard> codegen datamigration Maps

Creating Data Migration for Maps

Data migration created successfully in Module Maps

Visual Studio会提示你重新加载解决方案:

打开migrations文件,我们发现里面有一个Create方法,他创建了与MapRecord类相对应的表。

注意,Create会在特性启用的时候执行。

using System;

using System.Collections.Generic;

using System.Data;

using Maps.Models;

using Orchard.ContentManagement.Drivers;

using Orchard.ContentManagement.MetaData;

using Orchard.ContentManagement.MetaData.Builders;

using Orchard.Core.Contents.Extensions;

using Orchard.Data.Migration;

 

namespace Maps.DataMigrations {

public class Migrations : DataMigrationImpl {

 

public int Create() {

// Creating table MapRecord

SchemaBuilder.CreateTable("MapRecord", table => table

.ContentPartRecord()

.Column("Latitude", DbType.Double)

.Column("Longitude", DbType.Double)

);

 

ContentDefinitionManager.AlterPartDefinition(

typeof(MapPart).Name, cfg => cfg.Attachable());

 

return 1;

}

}

}

我们在Create方法中,执行了AlterPartDefinition函数,他的作用,就是表明,该元件,可以添加到任意的内容类型中。

 

我们添加该元件的Handler。Handler是指的该元件的行为,他具有事件句柄,还可以在元件渲染前操纵数据模型。在我们的handler中,我们告诉了元件,使用IRepository<MapRecord>来操纵数据。我们将该文件放在Handlers\MapHandler.cs:

using Maps.Models;

using Orchard.ContentManagement.Handlers;

using Orchard.Data;

 

namespace Maps.Handlers {

public class MapHandler : ContentHandler {

public MapHandler(IRepository<MapRecord> repository) {

Filters.Add(StorageFilter.For(repository));

}

}

}

 

我们为元件添加Driver。Driver定义了元件如何编辑、渲染、导入导出,他也是一种handler,我们可以将其看成简易的控制器。

内容项渲染的时候,会调用元件的Display方法,返回需要渲染的Shape,编辑的时候,会调用Edit方法,返回编辑Shape。Shape是具有数据和视图的,可以独立渲染的单元。我们将Driver文件放在Drivers\MapDriver.as :

using Maps.Models;

using Orchard.ContentManagement;

using Orchard.ContentManagement.Drivers;

 

namespace Maps.Drivers {

public class MapDriver : 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,

Prefix: Prefix));

}

//POST

protected override DriverResult Editor(

MapPart part, IUpdateModel updater, dynamic shapeHelper) {

 

updater.TryUpdateModel(part, Prefix, null, null);

return Editor(part, shapeHelper);

}

}

}

接下来我们添加视图。首先在Views文件夹下面,添加Parts和EditorTemplates/Parts 文件夹,在两个文件夹中,都添加Map.cshtml文件。

注意:Parts和EditorTemplates/Parts文件夹名称不能更改,是固定规范。Map.cshtml文件名称,需要和Driver中返回的Shape名称一致。

Views/EditorTemplates/Parts/Map.cshtml :

@model Maps.Models.MapPart

 

<fieldset>

<legend>Map Fields</legend>

 

<div class="editor-label">

@Html.LabelFor(model => model.Latitude)

</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>

Views/Parts/Map.cshtml :

<img alt="Location" border="1" src="http://maps.google.com/maps/api/staticmap?

&zoom=14

&size=256x256

&maptype=roadmap

&markers=color:blue|@Model.Latitude,@Model.Longitude

&sensor=false" />

在模块根目录,创建placement.info文件,里面记录了,元件在内容类型中的顺序和位置:

<Placement>

<Place Parts_Map="Content:10"/>

<Place Parts_Map_Edit="Content:7.5"/>

</Placement>

这个文件表明,Parts_Map Shape在内容类型中的顺序是10,Parts_Map_Edit在内容类型中的顺序是7.5

在后台管理页面,我们开启该特性

让我们在后台管理页面,创建一个Event内容类型,将地图元件附加到内容类型上面

单机Add按钮,选择要添加的内容类型

选择Map,点击保存

创建Event内容项,我们会看到,需要我们填写经度和纬度

在前端,我们就可以看到地图了

posted @ 2015-09-10 11:26  争世不悔  阅读(335)  评论(0编辑  收藏  举报