现在的位置: 首页 > 综合 > 正文

MVC学习之Partials和Master页面

2012年01月03日 ⁄ 综合 ⁄ 共 5250字 ⁄ 字号 评论关闭

Partials

ASP.NET MVC的一个设计理念是“Do Not Repeat Yourself”原则(通常称为DRY)。DRY设计帮助排除重复的代码和逻辑,让应用程序更快创建和更容易维护。
我们已经看到DRY原则应用在NerdDinner应用程序的一些方面了。如验证逻辑在Model层实现,在Controller的编辑和创建方法中均可执行;我们也跨越Edit、Details和Delete方法重用NotFound 视图模板;对View视图模板采用命名规范,这样在调用View() 辅助方法是不需要显式指定名称;另外在Edit和Create Action方法中重用DinnerFormViewModel类。
 
下面我们在View模板中应用DRY原则,减少重复的代码。
 
回顾Edit和Create视图模板
目前,我们使用2个不同的View视图模板 – Edit.aspx和Create.aspx – 来显示Dinner表单界面。我们可以比较一下这两个视图模板,发现非常相似。仅仅浏览器页面标题和表单标题不同,表单的布局和输入控件是一致的。
打开Edit.aspx和Create.aspx视图模板,我们发现这2个页面包含相同的表单布局和输入控件代码。这一重复意味着将来任何时候,如果我们添加或更改Dinner对象的属性,我们不得不改变两次 – 不推荐这样做。
 
使用Partial 视图模板
ASP.NET MVC支持定义Partial View 模板,封装一个页面的部分视图呈现逻辑。Partial提供了一个有效的方法定义视图呈现逻辑,然后在应用程序中多个页面重用。
为了消除Edit.aspx和Create.aspx 视图模板的重复,我们创建一个Partial View模板,命名为DinnerForm.ascx,封装两个页面中表单布局和输入元素相同的部分。具体操作:右键点击/Views/Dinners 目录,选择Add->View 菜单项:
 

 
在弹出的Add View对话框中,对新的视图命名DinnerForm,并选择Create a partial view 复选框,并指明将传入DinnerFormViewModel类:
 
http://forum.entlib.com/ 开源小组注:其中DinnerFormViewModel类的定义如下(代码可以放在DinnersController.cs文件中,也可以新添加一个类文件):
    public class DinnerFormViewModel
    {
        // Properties
        public Dinner Dinner { get; private set; }
        public SelectList Countries { get; private set; }
 
        // Constructor
        public DinnerFormViewModel(Dinner dinner)
        {
            Dinner = dinner;
            Countries = new SelectList(PhoneValidator.Countries, dinner.Country);
        }
   }
 
 
在点击Add 按钮后,Visual Studio 自动在\Views\Dinners 目录下创建一个新的DinnerForm.ascx 视图模板。
接着,我们从Edit.aspx/Create.aspx 视图模板中复制重复的表单到新的DinnerForm.ascx Partial 视图模板:
<%= Html.ValidationSummary("Please correct the errors and try again.") %>
<% using (Html.BeginForm())
   { %>
<fieldset>
    <p>
        <label for="Title">
            标题:</label>
        <%= Html.TextBox("Title", Model.Dinner.Title, new { style = "width: 300px; color:Red" })%>
        <%= Html.ValidationMessage("Title", "*") %>
    </p>
    <p>
        <label for="EventDate">
            事件日期:</label>
        <%= Html.TextBox("EventDate", Model.Dinner.EventDate) %>
        <%= Html.ValidationMessage("EventDate", "*") %>
    </p>
    <p>
        <label for="Description">
            描述:</label>
        <%= Html.TextArea("Description", Model.Dinner.Description, new { cols = 60, rows = 5 })%>
        <%= Html.ValidationMessage("Description", "*")%>
    </p>
    <p>
        <label for="Address">
            地址:</label>
        <%= Html.TextBox("Address", Model.Dinner.Address) %>
        <%= Html.ValidationMessage("Address", "*") %>
    </p>
    <p>
        <label for="Country">
            国家:</label>
        <%= Html.DropDownList("Country", Model.Countries) %>
        <%= Html.ValidationMessage("Country", "*") %>
    </p>
    <p>
        <label for="ContactPhone">
            联系电话:</label>
        <%= Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
        <%= Html.ValidationMessage("ContactPhone", "*") %>
    </p>
    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
<% } %>
 
接着,我们更新Edit和Create 视图模板,调用DinnerForm partial 模板,消除表单的重复内容。通过在视图模板中调用Html.RenderPartial(“DinnerForm”) 来实现:
 
Create.aspx视图文件:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerFormViewModel>" %>
 
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    招待一个宴会
</asp:Content>
<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        招待一个宴会</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>
 
Edit.aspx 视图文件:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerFormViewModel>" %>
 
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Edit:
    <%= Html.Encode(Model.Dinner.Title) %>
</asp:Content>
<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        编辑宴会信息</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>
 
在调用Html.RenderPartial() 方法时,你可以显式限定partial 模板的路径,如~Views/Dinners/DinnerForm.ascx。在上述代码中,我们利用ASP.NET MVC基于约定的命名规范,仅仅指定DinnerForm 作为partial模板。ASP.NET MVC首先基于约定查找视图目录(对DinnersController而言,查找/Views/Dinners目录),如果没有发现partial 模板,则继续在/Views/Shared目录下查找。
在调用Html.RenderPartial()方法,并传入partial视图名称,ASP.NET MVC将传入视图模板使用的Model和ViewData字典对象给partial视图。另外,Html.RenderPartial() 也有重载的版本,支持传入不同的Model对象和ViewData字典给partial视图去使用。当你仅仅想传递Model或ViewModel子集时,这一方法非常有用。
 
 
http://forum.entlib.com/ 开源论坛小组注:注意调用Html.RederPartial() 方法的代码 - <% Html.RenderPartial("DinnerForm"); %>,这里不能采用<% = %>,因为 Html.ReaderPartial() 方法不是返回一个字符串,而是直接输出内容到调用视图模板的输出流中。这是基于性能的考虑,通过这一实现,可以避免创建临时的字符串对象,降低内存的使用,提供整体应用程序的吞吐量。
另外一点需要注意的是,记得在Html.RednerPartial() 方法后使用分号,否则会导致编译器错误。这是因为<% %>代码块是一串代码语句,在C#代码中,需要通过分号标识语句结束。
 
使用Partial 视图模板简化代码
我们已经创建了DinnerForm Partial 视图模板消除重复的视图呈现逻辑,这是创建partial 视图模板的大部分原因。
有时,即使仅仅在一个地方调用,也需要创建partial视图模板。一个非常复杂的视图模板(View Template)通过提取和分割成多个patial视图模板,可以大大简化视图模板的阅读和维护。
例如,范例项目中Site.master 文件的代码如下。代码非常易于阅读,因为显示登录/退出的逻辑显示在右上角,封装在LogOnUserControl Partial视图中。
        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl"); %>
            </div>
            <div id="menucontainer">
                <ul id="menu">             
                    <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
                    <li><%= Html.ActionLink("About", "About", "Home")%></li>
                </ul>
            </div>
        </div>
 
在任何时候,如果你发现比较难理解视图模板中的HTML代码,就应该考虑是否提取和重构该视图模板为多个合适的partial视图。

抱歉!评论已关闭.