自定义影片界面

自定义字段标题

在我们影片列表和表单中,有一个叫 Runtime 的字段。该字段需要一个整数,表示影片时长(minutes),但在其标题描述中并没有该提示信息。让我们把其标题改为 Runtime (mins)。

有几种方法可以修改标题内容:修改服务器端表单的定义、修改服务器端列的定义、修改网格列表的脚本代码等。但让我们在核心的位置做修改,即修改实体本身,这样实体的标题在所有使用的地方都将得到修改。

当 Sergen 为电影(Movie)表生成代码时,创建了一个叫 MovieRow 的实体类,你可以在 Modules/MovieDB/Movie/MovieRow.cs 找到它。

这是摘自源文件的 Runtime 属性:

  1. namespace MovieTutorial.MovieDB.Entities
  2. {
  3. // ...
  4. [ConnectionKey("Default"), DisplayName("Movie"),
  5. InstanceName("Movie"), TwoLevelCached]
  6. public sealed class MovieRow : Row, IIdRow, INameRow
  7. {
  8. // ...
  9. [DisplayName("Runtime")]
  10. public Int32? Runtime
  11. {
  12. get { return Fields.Runtime[this]; }
  13. set { Fields.Runtime[this] = value; }
  14. }
  15. //...
  16. }
  17. }

我们会在后面讨论 entities(或 rows),现在让我们把注意力集中在更改字段名称的目标上。我们把 Runtime 属性的 DisplayName 特性的值修改为 *Runtime (mins):

  1. namespace MovieTutorial.MovieDB.Entities
  2. {
  3. // ...
  4. [ConnectionKey("Default"), DisplayName("Movie"), InstanceName("Movie"),
  5. TwoLevelCached]
  6. public sealed class MovieRow : Row, IIdRow, INameRow
  7. {
  8. // ...
  9. [DisplayName("Runtime (mins)")]
  10. public Int32? Runtime
  11. {
  12. get { return Fields.Runtime[this]; }
  13. set { Fields.Runtime[this] = value; }
  14. }
  15. //...
  16. }
  17. }

现在生成并运行应用程序,你会在网格列表和对话框中看到字段标题的变化。

在列不够宽时,列标题有 “…”,但是它会在提示信息中显示完整的标题。我们很快就会看到这是如何处理的。

Movies Runtime (Mins)

重写列的标题和宽度

到目前为止,一切看起来都还不错,如果我们想在网格列表(columns)或对话框(form)中显示另一个标题。我们可以重写它对应的定义文件。

我们先从 columns 开始,在 MovieRow.cs 旁边,你可以找到名为 MovieColumns.cs 的文件:

  1. namespace MovieTutorial.MovieDB.Columns
  2. {
  3. // ...
  4. [ColumnsScript("MovieDB.Movie")]
  5. [BasedOnRow(typeof(Entities.MovieRow))]
  6. public class MovieColumns
  7. {
  8. [EditLink, DisplayName("Db.Shared.RecordId"), AlignRight]
  9. public Int32 MovieId { get; set; }
  10. //...
  11. public Int32 Runtime { get; set; }
  12. }
  13. }

你可能会注意到这个 columns 的定义是基于电影实体(BasedOnRow 特性)。

任何写在这里的特性都将重写定义在实体类中的特性。

让我们把 DisplayName 特性添加到 Runtime 属性:

  1. namespace MovieTutorial.MovieDB.Columns
  2. {
  3. // ...
  4. [ColumnsScript("MovieDB.Movie")]
  5. [BasedOnRow(typeof(Entities.MovieRow))]
  6. public class MovieColumns
  7. {
  8. [EditLink, DisplayName("Db.Shared.RecordId"), AlignRight]
  9. public Int32 MovieId { get; set; }
  10. //...
  11. [DisplayName("Runtime in Minutes"), Width(150), AlignRight]
  12. public Int32 Runtime { get; set; }
  13. }
  14. }

现在,我们把列标题设置为 “Runtime in Minutes”。

实际上,我们添加了更多的特性。

其中,重写列的宽度为 150px。

Serenity 将根据字段类型和字符串长度自动设置列的宽度,除非你显式设置了宽度。

并且把列设为右对齐(还可设为居中对齐、左对齐)

再次生成并运行项目,我们将看到:

Movies Runtime Column

表单的标题保持原样,而网格的列标题已经发生了变化。

相反,如果我们想重写表单字段,我们就在 MovieForm.cs 做类似的步骤。

修改描述(Description)和剧情(Storyline)的编辑器类型

描述(Description)和剧情(Storyline)比标题(Title)字段长一点,因此,让我们把他们的编辑器类型改为文本域(textarea)。

MovieColumns.csMovieRow.cs 的同一文件夹中,打开 MovieForm.cs

  1. namespace MovieTutorial.MovieDB.Forms
  2. {
  3. //...
  4. [FormScript("MovieDB.Movie")]
  5. [BasedOnRow(typeof(Entities.MovieRow))]
  6. public class MovieForm
  7. {
  8. public String Title { get; set; }
  9. public String Description { get; set; }
  10. public String Storyline { get; set; }
  11. public Int32 Year { get; set; }
  12. public DateTime ReleaseDate { get; set; }
  13. public Int32 Runtime { get; set; }
  14. }
  15. }

在这两个属性中添加 TextAreaEditor 特性:

  1. namespace MovieTutorial.MovieDB.Forms
  2. {
  3. //...
  4. [FormScript("MovieDB.Movie")]
  5. [BasedOnRow(typeof(Entities.MovieRow))]
  6. public class MovieForm
  7. {
  8. public String Title { get; set; }
  9. [TextAreaEditor(Rows = 3)]
  10. public String Description { get; set; }
  11. [TextAreaEditor(Rows = 8)]
  12. public String Storyline { get; set; }
  13. public Int32 Year { get; set; }
  14. public DateTime ReleaseDate { get; set; }
  15. public Int32 Runtime { get; set; }
  16. }
  17. }

我为剧情(8 行)分配了更多的编辑行,因为与描述(3 行)相比剧情应该更长。

生成并运行项目后,我们得到:

Movies TextArea Editors

Serene 有几个编辑器类型可供选择。有些是基于字段的数据类型自动选取,而你需要显式地设置它们。

你还可以开发自己的编辑器类型。你可以把现有的编辑器类作为基类,或者从 stratch 中开发自己的编辑器,我们会在后面的章节介绍。

由于编辑器有点高,表单高度超出了 Serenity 默认的表单高度(约260px),所以现在我们有一个垂直滚动条,让我们删除这个垂直滚动条。

使用 CSS(Less)设置对话框的初始大小

Sergen 在 MovieTutorial.Web/Content/site/site.less 文件中生成一些影片对话框的 CSS。

如果你打开该文件,并滚动到底部,你将看到:

  1. /* ------------------------------------------------------------------------- */
  2. /* APPENDED BY CODE GENERATOR, MOVE TO CORRECT PLACE AND REMOVE THIS COMMENT */
  3. /* ------------------------------------------------------------------------- */
  4. .s-MovieDB-MovieDialog {
  5. > .size { width: 650px; }
  6. .caption { width: 150px; }
  7. }

你可以安全地删除这三行注释(由代码生成器添加)。这是提醒你将它们移动到更好的地方,如移到特定于此模块的 site.movies.less 文件(推荐)。

这些规则将应用于有 .s-MovieDB-MovieDialog 样式类的元素。在默认情况下,我们的对话框具有这样的样式类: “s-“ + 模块名 + “-“ + 类名。

在第二行中指定该对话框的默认宽度是 650px 。

在第三行中,我们指定该字段标签长度应该是 150px(@l:150px)。

让我们改变对话框初始高度为 500px(桌面模式),这样它就不会出现垂直滚动条:

  1. .s-MovieDialog {
  2. > .size { width: 650px); height: 500px; }
  3. .caption { width: 150px; }
  4. }

要将此更改应用到你的对话框,你需要生成解决方案。在生成项目时,”site.less” 文件被编译到一个 “site.css” 文件。现在生成项目并刷新页面。

Movie Dialog 500px

上面所说的 桌面模式 将很快变得直观。Serenity 对话框默认是响应式的。让我们把浏览器窗口的宽度调整为 350px 左右。我会用 Chrome 浏览器的移动模式切换到 iphone 6:

Movie Dialog iPhone6

现在改为 iPad 横向模式:

Movie Dialog iPad

因此,我们在这里对桌面模式设置的高度是很有用意的。对话框将变为响应式,不需要使用 CSS 的 @media 查询就可对移动设备特定大小模式保持敏感的响应。

修改页面标题

我们的页面有标题 Movie,让我们把它修改为 Movies

再次打开 MovieRow.cs

  1. namespace MovieTutorial.MovieDB.Entities
  2. {
  3. // ...
  4. [ConnectionKey("Default"), DisplayName("Movie"), InstanceName("Movie"),
  5. TwoLevelCached]
  6. public sealed class MovieRow : Row, IIdRow, INameRow
  7. {
  8. [DisplayName("Movie Id"), Identity]
  9. public Int32? MovieId

把 DisplayName 特性的值改为 Movies。这是引用此表时使用的名称,它通常是复数。此特性用于确定默认页面的标题。

也可以在 MoviePage.Index.cshtml 文件中重写页面标题。但像往常一样,我们习惯从核心着手,以便在其它地方可以重用这些信息。

实例名对应单数名称,并在网格的新增记录(新电影)按钮中使用,也决定了对话框标题(例如编辑电影)。

  1. namespace MovieTutorial.MovieDB.Entities
  2. {
  3. // ...
  4. [ConnectionKey("Default"), DisplayName("Movies"), InstanceName("Movie"),
  5. TwoLevelCached]
  6. public sealed class MovieRow : Row, IIdRow, INameRow
  7. {
  8. [DisplayName("Movie Id"), Identity]
  9. public Int32? MovieId