display模版详细介绍

ASP.NET MVC 2 Templates, Part 4: Custom Object Templates

Series Index

Customizing Templates

In Part 3, we saw what the default templates would look like if we’d written them as .ascx files. In this blog post, we’ll discuss some of the customizations you can make to the Object templates to enable different features and different displays for your template-based UI.

For these examples, here are the models, controller, and views that we’ll be using.

Models/SampleModel.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
 
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.microsoft.com/",
        };
    }
 
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.ComponentModel.DataAnnotations;
 
[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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System.Web.Mvc;
 
public class HomeController : Controller {
    static SampleModel model = SampleModel.Create();
 
    public ViewResult 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

1
2
3
4
5
6
7
8
9
10
11
12
<%@ Page
    Language="C#"
    MasterPageFile="~/Views/shared/Site.master"
    Inherits="ViewPage<SampleModel>" %>
 
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h3>Details</h3>
    <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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ Page
    Language="C#"
    MasterPageFile="~/Views/shared/Site.master"
    Inherits="ViewPage<SampleModel>" %>
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h3>Edit</h3>
    <% 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>

 

The Default Display

When we show this home controller without any customizations, this is what the details page looks like:

Default Display

And this is our edit page:

Default Editor

 

Tabular Layout

One of the more commonly requested layouts is to do a tabular layout inside of the linear name/value, name/value layout that we do by default. Notice that the editor version of this layout also adds asterisks to the label for required fields.

Views/Shared/DisplayTemplates/Object.ascx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ 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>
<% } %>

Which creates this layout:

Tabular Display

Views/Shared/EditorTemplates/Object.ascx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ 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>
<% } %>

Which creates this layout:

 

Tabular Editor

Shallow Dive vs. Deep Dive

In the screenshots above, ChildModel is showing as “(null value)”. ChildModel is itself a complex model, so it follows the rules for shallow dive vs. deep dive. Before we have a child model object, it’s showing the NullDisplayText as we set in the attribute in the model above.

Notice that even in edit mode above, we can’t edit the child model. That’s because the shallow dive logic prevents us from presenting a recursive editing UI.

If we change the Editor template above and remove the first “if” statement (which is what prevents the deep dive), then the editor will now show us editing fields for the child model:

Tabular Editor with Deep Dive enabled

And now our display shows:

Tabular Display with child model (shallow dive)

Since we haven’t changed our Object Display template, we still get a shallow dive on this object. Further, it’s showing us the full name because we’ve used the DataAnnotations [DisplayColumn] attribute to say “display this property when showing this complex object in shallow form”. We’ve pointed [DisplayColumn] to a synthesized property called FullName, which we don’t normally show because we’ve annotated it with [ScaffoldColumn(false)].

If we change the Object Display template to do a deep dive, then we would see this:

Tabular Display with Deep Dive

Wrapping Up

In this blog post, I’ve shown you some of the ways you can customize the Object template to get different displays for your templates. That includes a tabular display instead of a linear display, adding asterisks to field names when fields are required, as well as enabling Deep Dive scenarios for complex objects inside of complex objects. In the next blog post, I’ll examine changing all the templates to enable an entirely different layout system centered around Master pages, inspired by Eric Hexter’s Opinionated Input Builders blog post series.

 

 

文章引自:http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

posted on 2015-02-27 16:20  小呀么小二郎  阅读(279)  评论(0编辑  收藏  举报

导航