zoukankan      html  css  js  c++  java
  • ASP.NET MVC 2 Templates, Part 4: Custom Object Templates[翻译]

    原文链接

    ASP.NET MVC 2 Templates, Part 1: Introduction[翻译]

    ASP.NET MVC 2 Templates, Part 2: ModelMetadata[翻译]

    ASP.NET MVC 2 Templates, Part 3: Default Templates[翻译]

    自定义模版

    在Part 3,我们看到把内置模版写成.ascx文件是什么样子的.在这篇文章,我们会讨论Object模版的一些自定义方法,使得其有不同的特性和不同的显示模版UI.

    下面就是这个例子的代码:

    Models/SampleModel.cs

    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    
    namespace TemplatesPart4.Models
    {
        public class SampleModel
        {
            public static SampleModel Create() {
                return new SampleModel {
                    Boolean = true,
                    EmailAddress = "admin@contoso.com",
                    Decimal = 21.1234M,
                    Integer = 42,
                    Hidden = "Uneditable",
                    HiddenAndInvisible = "Also uneditable",
                    Html = "This is <b>HTML</b> enabled",
                    MultilineText = "This\r\nhas\r\nmultiple\r\nlines",
                    NullableBoolean = null,
                    Password = "supersecret",
                    String = "A simple string",
                    Url = "http://www.cnblogs.com/lemontea",
                    ChildModel = new ChildModel {
                        FirstName = "zhang",
                        LastName = "weiwen",
                    }
                };
            }
    
            public bool Boolean { get; set; }
    
            [DataType(DataType.EmailAddress)]
            public string EmailAddress { get; set; }
    
            public decimal Decimal { get; set; }
    
            [HiddenInput]
            public string Hidden { get; set; }
    
            [HiddenInput(DisplayValue = false)]
            public string HiddenAndInvisible { get; set; }
    
            [DataType(DataType.Html)]
            public string Html { get; set; }
    
            [Required]
            [Range(10, 100)]
            public int Integer { get; set; }
    
            [DataType(DataType.MultilineText)]
            public string MultilineText { get; set; }
    
            public bool? NullableBoolean { get; set; }
    
            [DataType(DataType.Password)]
            public string Password { get; set; }
    
            public string String { get; set; }
    
            [DataType(DataType.Url)]
            public string Url { get; set; }
    
            [DisplayFormat(NullDisplayText = "(null value)")]
            public ChildModel ChildModel { get; set; }
        }
    }

    Models/ChildModel.cs

    using System.ComponentModel.DataAnnotations;
    
    namespace TemplatesPart4.Models
    {
        [DisplayColumn("FullName")]
        public class ChildModel
        {
            [Required, StringLength(25)]
            public string FirstName { get; set; }
    
            [Required, StringLength(25)]
            public string LastName { get; set; }
    
            [ScaffoldColumn(false)]
            public string FullName {
                get {
                    return FirstName + " " + LastName;
                }
            }
    
        }
    }

    Controllers/HomeController.cs

    using System.Web.Mvc;
    using TemplatesPart4.Models;
    
    namespace TemplatesPart4.Controllers
    {
        public class HomeController : Controller
        {
            static SampleModel model = SampleModel.Create();
    
            public ActionResult Index() {
                return View(model);
            }
    
            public ViewResult Edit() {
                return View(model);
            }
    
            [HttpPost]
            [ValidateInput(false)]
            public ActionResult Edit(SampleModel editedModel) {
                if (ModelState.IsValid) {
                    model = editedModel;
                    return RedirectToAction("Details");
                }
    
                return View(editedModel);
            }
        }
    }

    Views/Home/Index.aspx

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TemplatesPart4.Models.SampleModel>" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Index
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        <h2>Index</h2>
        <fieldset style="padding: 1em; margin: 0; border: solid 1px #999;">
            <%= Html.DisplayForModel() %>
        </fieldset>
        <p>
            <%= Html.ActionLink("Edit", "Edit") %></p>
    </asp:Content>
    

    Views/Home/Edit.aspx

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TemplatesPart4.Models.SampleModel>" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Edit
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        <h2>Edit</h2>
        <% using (Html.BeginForm()) { %>
        <fieldset style="padding: 1em; margin: 0; border: solid 1px #999;">
            <%= Html.ValidationSummary("Broken stuff:") %>
            <%= Html.EditorForModel() %>
            <input type="submit" value="  Submit  " />
        </fieldset>
        <% } %>
        <p>
            <%= Html.ActionLink("Details", "Index") %></p>
    </asp:Content>
    

    默认显示

    运行,界面如下图,这时没有任何自定义项:

    image

    译注:原文中的截图会生成ChildModel,(null value),不知是不是版本原因,ASP.NET MVC 2 RTM版本的Object模版应该是不会渲染这个属性的(!metadata.IsComplexType),前面的文章和下面同理.RTM官方版本的Object模版如下:

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <script runat="server">
        bool ShouldShow(ModelMetadata metadata) {
            return metadata.ShowForDisplay
                && metadata.ModelType != typeof(System.Data.EntityState)
                && !metadata.IsComplexType
                && !ViewData.TemplateInfo.Visited(metadata);
        }
    </script>
    <% if (Model == null) { %>
        <%= ViewData.ModelMetadata.NullDisplayText %>
    <% } else if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
        <%= ViewData.ModelMetadata.SimpleDisplayText %>
    <% } else { %>
        <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => ShouldShow(pm))) { %>
            <% if (prop.HideSurroundingHtml) { %>
                <%= Html.Display(prop.PropertyName) %>
            <% } else { %>
                <% if (!String.IsNullOrEmpty(prop.GetDisplayName())) { %>
                    <div class="display-label"><%= prop.GetDisplayName() %></div>
                <% } %>
                <div class="display-field"><%= Html.Display(prop.PropertyName) %></div>
            <% } %>
        <% } %>
    <% } %>

    image

    编辑页面:

    image

    表格布局

    表格布局是最普通的名值对布局.注意编辑版本的模版在required字段的label前添加星号(*).

    Views/Shared/DisplayTemplates/Object.ascx

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <% if (Model == null) { %>
    <%= ViewData.ModelMetadata.NullDisplayText %>
    <% }
       else if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
    <%= ViewData.ModelMetadata.SimpleDisplayText %>
    <% }
       else { %>
    <table cellpadding="0" cellspacing="0" border="0">
        <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) { %>
        <% if (prop.HideSurroundingHtml) { %>
        <%= Html.Display(prop.PropertyName) %>
        <% }
           else { %>
        <tr>
            <td>
                <div class="display-label" style="text-align: right;">
                    <%= prop.GetDisplayName() %>
                </div>
            </td>
            <td>
                <div class="display-field">
                    <%= Html.Display(prop.PropertyName) %>
                </div>
            </td>
        </tr>
        <% } %>
        <% } %>
    </table>
    <% } %>

    截图:

    image

    Views/Shared/EditorTemplates/Object.ascx

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <% if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
    <%= ViewData.ModelMetadata.SimpleDisplayText %>
    <% }
       else { %>
    <table cellpadding="0" cellspacing="0" border="0">
        <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) { %>
        <% if (prop.HideSurroundingHtml) { %>
        <%= Html.Editor(prop.PropertyName) %>
        <% }
           else { %>
        <tr>
            <td>
                <div class="editor-label" style="text-align: right;">
                    <%= prop.IsRequired ? "*" : "" %>
                    <%= Html.Label(prop.PropertyName) %>
                </div>
            </td>
            <td>
                <div class="editor-field">
                    <%= Html.Editor(prop.PropertyName) %>
                    <%= Html.ValidationMessage(prop.PropertyName, "*") %>
                </div>
            </td>
        </tr>
        <% } %>
        <% } %>
    </table>
    <% } %>
    

    截图:

    image

    Shallow Dive vs. Deep Dive

    在上面的截图中,ChildModel显示为"(null value)",ChildModel是一个复合model,所以所以它遵循shallow dive的原则,在我们有一个ChildModel对象前,它显示了我们在model设置的NullDisplayText特性值.

    注意即使在编辑版本中,我们也不能编辑ChildModel,因为shallow dive原则阻止我们递归呈现编辑UI.

    如果我们改变编辑模版,把第一个 if 语句去掉(阻止deep dive的那个),这时就会为ChildModel显示可编辑字段:

    image

    在SampleModel的Create()方法中加入:

    ChildModel = new ChildModel {
        FirstName = "zhang",
        LastName = "weiwen",
    }

    截图:

    image

    因为我们还没有改变我们的Object显示模版,我们仍然使用shallow dive原则.另外,它显示全名是因为定义ChildModel时使用了DataAnnotations特性[DisplayColumn]来说明"当要显示这个复合对象时显示这一列",我门指定[DisplayColumn]给命名为FullName的综合属性,这个属性通常不会显示,因为我们附注了[ScaffoldColumn(false)].

    如果我们改变Object的显示模版为deep dive,那么显示如下:

    image

    结语

    这篇文章,我给你介绍了几个自定义Object模版的方法,用于显示不同的界面.包括表格布局代替行布局,required字段前添加星号,而且实现复合对象嵌套复合对象的Deep Dive场景.下一篇文章,我会怎么改变所有模版实现围绕母版页布局,灵感来自Eric Hexter的文章Opinionated Input Builders.

  • 相关阅读:
    配置apache的文件访问路径
    php 常量const
    php接口interface的使用
    php 抽象类abstract
    php 面向对象三大特点:封装、继承、多态
    程序员的情怀《从前慢》木心
    php static静态属性和静态方法
    php面向对象的构造方法与析构方法
    关于php变量的赋值和引用的区别
    angular4.0微信oAuth第三方认证的正确方式
  • 原文地址:https://www.cnblogs.com/lemontea/p/2248404.html
Copyright © 2011-2022 走看看