Orchard:生成一个自定义字段类型
2011-02-17 12:31
281 查看
在Orchard中定义新的content types时可以使用字段,现在Orchard只内置了一个文本类型字段,在实际应用中,我们肯定会遇到添加自己的字段类型,然后在新的content types上使用。这篇文章将教给大家的是在http://orcharddatetimefield.codeplex.com中的自定义日期时间数据类型。如果对如何生成一个模块不清楚,可以先看看本系列的前几篇文章。
现在在Modules目录下有一个新的目录:CustomFields,更改module.txt:
View Code
这里我们定义了两个features,因为这个模块最后包括多个字段,我们想要区分这个模块的默认功能和日期字段功能,这个也正好可以演示一下分类和依赖的使用。
View Code
这个自定义字段DateTimeField是从ContentField继承下来的,ContentField提供一些字段值存储等服务。这个字段将存储为strings。
View Code
View Code
这里我们定义了一个设类,这个类是个很简单的类,Display是一个枚举值
View Code
DateTimeFieldDriver 从 ContentFieldDriver 继承下来。
一开始通过依赖注入获取localizer 依赖对象,以便我们能够通过代码获取本地化字符。静态的方法GetPrefix是一个用来定义字段类型示例在数据库中唯一列名的前缀。
Display和Editor获取字段的设置和值来构建shapes。
在Views/Fields下新增文件Custom.DateTime.cshtml:
View Code
在Views/EditorTemplates/Fields 下生成文件Custom.DateTime.cshtml:
为了指定显示顺序和位置,在项目根目录下增加文件Placement.info:
View Code
到现在还没有完全做完,我们还需要关心如何管理和持久化字段的设置,在Settings目录下增加文件DateTimeFieldEditorEvents.cs:
View Code
这个类似与一个driver,但是是field settings。第一个方法获得设置并且决定展现的模板,第二个方法从提交窗口中更新模型值。
生成目录Views\DefinitionTemplates,添加字段的编辑摸板文件DateTimeFieldSettings.cshtml:
View Code
View Code
View Code
参考:Writing a content field http://orcharddatetimefield.codeplex.com/
推荐:你可能需要的在线电子书
我的新浪围脖: http://t.sina.com.cn/openexpressapp
欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]
目标
这个练习做完之后,我们将新增一个新的字段类型,使用界面如下图所示:有一个日期和时间编辑器生成一个模块
codegen module CustomFields /IncludeInSolution:true
现在在Modules目录下有一个新的目录:CustomFields,更改module.txt:
View Code
Name: CustomFields AntiForgery: enabled Author: Me Website: http://orcharddatetimefield.codeplex.com Version: 0.6.1 OrchardVersion: 0.8.0 Description: A bunch of custom fields for use in your custom content types. Features: CustomFields: Description: Custom fields for Orchard. Category: Fields DateTimeField: Description: A date and time field with a friendly UI. Category: Fields Dependencies: CustomFields, Orchard.jQuery, Common, Settings
这里我们定义了两个features,因为这个模块最后包括多个字段,我们想要区分这个模块的默认功能和日期字段功能,这个也正好可以演示一下分类和依赖的使用。
生成字段
在CustomFields目录下生成目录Fields,添加文件DateTimeField.cs:View Code
using System; using System.Globalization; using Orchard.ContentManagement; using Orchard.ContentManagement.FieldStorage; using Orchard.Environment.Extensions; namespace CustomFields.DateTimeField.Fields { [OrchardFeature("DateTimeField")] public class DateTimeField : ContentField { public DateTime? DateTime { get { var value = Storage.Get<string>(); DateTime parsedDateTime; if (System.DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { return parsedDateTime; } return null; } set { Storage.Set(value == null ? String.Empty : value.Value.ToString(CultureInfo.InvariantCulture)); } } } }
这个自定义字段DateTimeField是从ContentField继承下来的,ContentField提供一些字段值存储等服务。这个字段将存储为strings。
生成一个view model
生成一个或多个view models虽然不是强制的,但是一个好的实践。View model将被用来封装model用于展现而用的模型。在一个新的ViewModels目录下添加文件DateTimeFieldViewModel.cs:View Code
namespace CustomFields.DateTimeField.ViewModels { public class DateTimeFieldViewModel { public string Name { get; set; } public string Date { get; set; } public string Time { get; set; } public bool ShowDate { get; set; } public bool ShowTime { get; set; } } }
生成字段设置
Create a Settings folder and add the following DateTimeFieldSettings.cs file to it:View Code
namespace CustomFields.DateTimeField.Settings { public enum DateTimeFieldDisplays { DateAndTime, DateOnly, TimeOnly } public class DateTimeFieldSettings { public DateTimeFieldDisplays Display { get; set; } } }
这里我们定义了一个设类,这个类是个很简单的类,Display是一个枚举值
写一个driver
在Drivers目录下添加文件DateTimeFieldDriver.cs:View Code
using System; using CustomFields.DateTimeField.ViewModels; using JetBrains.Annotations; using Orchard; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using CustomFields.DateTimeField.Settings; using Orchard.Localization; namespace CustomFields.DateTimeField.Drivers { [UsedImplicitly] public class DateTimeFieldDriver : ContentFieldDriver<Fields.DateTimeField> { public IOrchardServices Services { get; set; } // EditorTemplates/Fields/Custom.DateTime.cshtml private const string TemplateName = "Fields/Custom.DateTime"; public DateTimeFieldDriver(IOrchardServices services) { Services = services; T = NullLocalizer.Instance; } public Localizer T { get; set; } private static string GetPrefix(ContentField field, ContentPart part) { // handles spaces in field names return (part.PartDefinition.Name + "." + field.Name) .Replace(" ", "_"); } protected override DriverResult Display( ContentPart part, Fields.DateTimeField field, string displayType, dynamic shapeHelper) { var settings = field.PartFieldDefinition.Settings .GetModel<DateTimeFieldSettings>(); var value = field.DateTime; return ContentShape("Fields_Custom_DateTime", // key in Shape Table // this is the actual Shape which will be resolved // (Fields/Custom.DateTime.cshtml) s => s.Name(field.Name) .Date(value.HasValue ? value.Value.ToLocalTime().ToShortDateString() : String.Empty) .Time(value.HasValue ? value.Value.ToLocalTime().ToShortTimeString() : String.Empty) .ShowDate( settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly) .ShowTime( settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly) ); } protected override DriverResult Editor(ContentPart part, Fields.DateTimeField field, dynamic shapeHelper) { var settings = field.PartFieldDefinition.Settings .GetModel<DateTimeFieldSettings>(); var value = field.DateTime; if (value.HasValue) { value = value.Value.ToLocalTime(); } var viewModel = new DateTimeFieldViewModel { Name = field.Name, Date = value.HasValue ? value.Value.ToLocalTime().ToShortDateString() : "", Time = value.HasValue ? value.Value.ToLocalTime().ToShortTimeString() : "", ShowDate = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly, ShowTime = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly }; return ContentShape("Fields_Custom_DateTime_Edit", () => shapeHelper.EditorTemplate( TemplateName: TemplateName, Model: viewModel, Prefix: GetPrefix(field, part))); } protected override DriverResult Editor(ContentPart part, Fields.DateTimeField field, IUpdateModel updater, dynamic shapeHelper) { var viewModel = new DateTimeFieldViewModel(); if (updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null)) { DateTime value; var settings = field.PartFieldDefinition.Settings .GetModel<DateTimeFieldSettings>(); if (settings.Display == DateTimeFieldDisplays.DateOnly) { viewModel.Time = DateTime.Now.ToShortTimeString(); } if (settings.Display == DateTimeFieldDisplays.TimeOnly) { viewModel.Date = DateTime.Now.ToShortDateString(); } if (DateTime.TryParse( viewModel.Date + " " + viewModel.Time, out value)) { field.DateTime = value.ToUniversalTime(); } else { updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid date and time", field.Name)); field.DateTime = null; } } return Editor(part, field, shapeHelper); } } }
DateTimeFieldDriver 从 ContentFieldDriver 继承下来。
一开始通过依赖注入获取localizer 依赖对象,以便我们能够通过代码获取本地化字符。静态的方法GetPrefix是一个用来定义字段类型示例在数据库中唯一列名的前缀。
Display和Editor获取字段的设置和值来构建shapes。
写模板
在Views目录下生成一个Fields和EditorTemplates目录,然后在EditorTemplates下生成一个Fields目录。在Views/Fields下新增文件Custom.DateTime.cshtml:
View Code
<p class="text-field"><span class="name">@Model.Name:</span> @if(Model.ShowDate) { <text>@Model.Date</text> } @if(Model.ShowTime) { <text>@Model.Time</text> } </p>
在Views/EditorTemplates/Fields 下生成文件Custom.DateTime.cshtml:
为了指定显示顺序和位置,在项目根目录下增加文件Placement.info:
View Code
@model CustomFields.DateTimeField.ViewModels.DateTimeFieldViewModel @{ Style.Include("datetime.css"); Style.Require("jQueryUI_DatePicker"); Style.Require("jQueryUtils_TimePicker"); Style.Require("jQueryUI_Orchard"); Script.Require("jQuery"); Script.Require("jQueryUtils"); Script.Require("jQueryUI_Core"); Script.Require("jQueryUI_Widget"); Script.Require("jQueryUI_DatePicker"); Script.Require("jQueryUtils_TimePicker"); } <fieldset> <label for="@Html.FieldIdFor(m => Model.Date)">@Model.Name</label> @if ( Model.ShowDate ) { <label class="forpicker" for="@Html.FieldIdFor(m => Model.Date)">@T("Date")</label> <span class="date">@Html.EditorFor(m => m.Date)</span> } @if ( Model.ShowTime ) { <label class="forpicker" for="@Html.FieldIdFor(m => Model.Time)">@T("Time")</label> <span class="time">@Html.EditorFor(m => m.Time)</span> } @if(Model.ShowDate) { <text>@Html.ValidationMessageFor(m=>m.Date)</text> } @if(Model.ShowTime) { <text>@Html.ValidationMessageFor(m=>m.Time)</text> } </fieldset> @using(Script.Foot()) { <script type="text/javascript"> $(function () { $("#@Html.FieldIdFor(m => Model.Date)").datepicker(); $("#@Html.FieldIdFor(m => Model.Time)").timepickr(); }); </script> }
View Code
<Placement>
<Place Fields_Custom_DateTime_Edit="Content:2.5"/>
<Place Fields_Custom_DateTime="Content:2.5"/>
</Placement>
管理字段设置
到现在还没有完全做完,我们还需要关心如何管理和持久化字段的设置,在Settings目录下增加文件DateTimeFieldEditorEvents.cs:View Code
using System.Collections.Generic; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.ViewModels; namespace CustomFields.DateTimeField.Settings { public class DateTimeFieldEditorEvents : ContentDefinitionEditorEventsBase { public override IEnumerable<TemplateViewModel> PartFieldEditor(ContentPartFieldDefinition definition) { if (definition.FieldDefinition.Name == "DateTimeField") { var model = definition.Settings.GetModel<DateTimeFieldSettings>(); yield return DefinitionTemplate(model); } } public override IEnumerable<TemplateViewModel> PartFieldEditorUpdate( ContentPartFieldDefinitionBuilder builder, IUpdateModel updateModel) { var model = new DateTimeFieldSettings(); if (updateModel.TryUpdateModel( model, "DateTimeFieldSettings", null, null)) { builder.WithSetting("DateTimeFieldSettings.Display", model.Display.ToString()); } yield return DefinitionTemplate(model); } } }
这个类似与一个driver,但是是field settings。第一个方法获得设置并且决定展现的模板,第二个方法从提交窗口中更新模型值。
生成目录Views\DefinitionTemplates,添加字段的编辑摸板文件DateTimeFieldSettings.cshtml:
View Code
@model CustomFields.DateTimeField.Settings.DateTimeFieldSettings @using CustomFields.DateTimeField.Settings; <fieldset> <label for="@Html.FieldIdFor(m => m.Display)" class="forcheckbox">@T("Display options")</label> <select id="@Html.FieldIdFor(m => m.Display)" name="@Html.FieldNameFor(m => m.Display)"> @Html.SelectOption(DateTimeFieldDisplays.DateAndTime, Model.Display == DateTimeFieldDisplays.DateAndTime, T("Date and time").ToString()) @Html.SelectOption(DateTimeFieldDisplays.DateOnly, Model.Display == DateTimeFieldDisplays.DateOnly, T("Date only").ToString()) @Html.SelectOption(DateTimeFieldDisplays.TimeOnly, Model.Display == DateTimeFieldDisplays.TimeOnly, T("Time only").ToString()) </select> @Html.ValidationMessageFor(m => m.Display) </fieldset>
更新项目文件
打开项目文件CustomFields.csproj:View Code
<Compile Include="Drivers\DateTimeFieldDriver.cs" /> <Compile Include="Fields\DateTimeField.cs" /> <Compile Include="Settings\DateTimeFieldEditorEvents.cs" /> <Compile Include="Settings\DateTimeFieldSettings.cs" /> <Compile Include="ViewModels\DateTimeFieldViewModel.cs" />
添加样式
Create a Styles directory and create the following datetime.css:View Code
html.dyn label.forpicker { display:none; } html.dyn input.hinted { color:#ccc; font-style:italic; } .date input{ width:10em; } .time input { width:6em; }
使用字段
为了能够使用心得字段,首先必须打开Orchard.ContentTypes功能,还需要打开DateTimeField 功能。参考:Writing a content field http://orcharddatetimefield.codeplex.com/
推荐:你可能需要的在线电子书
我的新浪围脖: http://t.sina.com.cn/openexpressapp
欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]
相关文章推荐
- Orchard:生成一个自定义字段类型
- Orchard:生成一个自定义字段类型
- 在Orchard中创建一个自定义字段类型
- PowerDesign 使用 用户自定义字段类型 domain 后 生成物理模型图 生成的sql脚本 类型 替换问题
- 使用VS2010开发一个简单的自定义字段类型
- 使用VS2010开发一个简单的自定义字段类型
- 利用sqlite创建一个数据user,其含有一张表person,该person表中含有三个列,其中第一字段为主键int类型的,其他两个字段自定义数据类型和名称。
- 如何判断一个NVARCHAR类型的字段中包含中文(这里只为简体中文)
- 自定义列表字段类型(0)
- 查询某一个表的字段和数据类型
- PyCon 2011 - Hidden Treasures of the Python Standard Library - 自定义sqlite3数据表字段数据类型
- Insert 一个字段类型是自动增量的导入数据
- 将String类型的二维数组中的元素用FileOutputStream的write方法生成一个文件
- 给定一个一oracle建表的sql语句,解析读出的字符串,将表名、字段名、字段类型数据取出,怎么实现啊?
- 微信自定义菜单,php配置一个多维数组,通过json_encode()生成json字符串,中文会转为\uxxxx,微信报错!
- 如何判断一个NVARCHAR类型的字段中包含中文
- 织梦5.6 5.7(DedeCMS)自定义图片类型字段的调用
- 【原】一道SQL题(根据一个字段值的后四位的两两差,生成对应的数据行)
- 批量生成修改数据库表字段类型SQL脚本
- 为表建立一个主键,设置子增量主键,了解常用数据表字段类型