• ASP.NET MVC学习之模型模板篇


    一.前言

    如果你使用ASP.NET MVC制作后台一定会爱上它的EditorForModalDisplayForModalLabelForModal方法,因为这些方法可以将模型直接变成对应的标签,省了不少事,但是对于一些苛刻的人来说,一定想自定义,下面我们会先介绍如何使用,然后介绍如何自定义。

     

    二.正文

    1.输出模型

    首先我们要新建一个Home控制器,对应的还要有一个Index动作,和Index视图,接着我们在Modal下新建一个Address类:

     1 namespace MvcStudy.Models
     2 {
     3     public class Address
     4     {
     5         public string Line1 { get; set; }
     6         public string Line2 { get; set; }
     7         public string City { get; set; }
     8         public string PostalCode { get; set; }
     9         public string Country { get; set; }
    10     }
    11 }

    接着再新建一个Role枚举:

    1 namespace MvcStudy.Models
    2 {
    3     public enum Role
    4     {
    5         Admin,
    6         User,
    7         Guest
    8     }
    9 }

    最后新建一个Person类:

     1 namespace MvcStudy.Models
     2 {
     3     public partial class Person
     4     {
     5         public int PersonId { get; set; }
     6         public string FirstName { get; set; }
     7         public string LastName { get; set; }
     8         public DateTime BirthDate { get; set; }
     9         public Address HomeAddress { get; set; }
    10         public bool IsApproved { get; set; }
    11         public Role Role { get; set; }
    12     }
    13 }

    然后我们在Home控制器的Index方法中写入如下代码:

     1 namespace MvcStudy.Controllers
     2 {
     3     public class HomeController : Controller
     4     {
     5         public ActionResult Index()
     6         {
     7             Person p = new Person
     8             {
     9                 PersonId = 1,
    10                 HomeAddress = new Address
    11                 {
    12                     City = "zj",
    13                     Country = "js",
    14                     Line1 = "111",
    15                     Line2 = "222",
    16                     PostalCode = "asdsa"
    17                 },
    18                 Role = Models.Role.User,
    19                 BirthDate = DateTime.Now,
    20                 FirstName = "y",
    21                 LastName = "zf",
    22                 IsApproved = false
    23             };
    24             return View(p);
    25         }
    26     }
    27 }

    同时还要确保Index视图的model的类型是Person类型,如果不是可以在最顶部加上如下代码:

    @model MvcStudy.Models.Person

    接着我们打开Index视图,在其中写入@Html.EditorForModel(),运行之后我们可以看到页面上输出了该类的属性:

    图 1.1

    但是我们可以发现PersonId也输出了而且还可以编辑,这可不是我们所想要的,所以我们要在模型的PersonId上加上HiddenInput注解属性,重新编译后我们可以看到PersonId已经不可编辑了:

    但是有时我们根本不想让它显示出来,这个时候我们需要修改HiddenInput注解属性,将DisplayValue设置为false即可,但是你可以通过查看页面的html源代码看到存在一个隐藏的input标签,当然如果你根本不想让这个属性存在于页面中我们可以将HiddenInput修改成[ScaffoldColumn(false)]即可。

     

    通过图1.1我们可以发现label中显示的都是该属性的名称,并不符合实际的使用习惯,所以我们还要给这些属性加上该显示的名称:

     1 namespace MvcStudy.Models
     2 {
     3     public partial class Person
     4     {
     5         [ScaffoldColumn(false)]
     6         public int PersonId { get; set; }
     7         [Display(Name = "")]
     8         public string FirstName { get; set; }
     9         [Display(Name = "")]
    10         public string LastName { get; set; }
    11         [Display(Name = "生日")]
    12         public DateTime BirthDate { get; set; }
    13         public Address HomeAddress { get; set; }
    14         [Display(Name = "是否启用")]
    15         public bool IsApproved { get; set; }
    16         [Display(Name = "角色")]
    17         public Role Role { get; set; }
    18     }
    19 }

    重新编译之后我们可以看到页面变成了如下所示:

    我们可以看到字符串都使用input去呈现,但是有时候这样并不符合实际情况,那么我们就要修改属性的DataType类型,比如我们将姓修改成富文本,修改Person代码:

     1 namespace MvcStudy.Models
     2 {
     3     public partial class Person
     4     {
     5         [ScaffoldColumn(false)]
     6         public int PersonId { get; set; }
     7         [Display(Name = "")]
     8         [DataType(DataType.Text)]
     9         public string FirstName { get; set; }
    10         [Display(Name = "")]
    11         [DataType(DataType.MultilineText)]
    12         public string LastName { get; set; }
    13         [Display(Name = "生日")]
    14         [DataType(DataType.DateTime)]
    15         public DateTime BirthDate { get; set; }
    16         public Address HomeAddress { get; set; }
    17         [Display(Name = "是否启用")]
    18         public bool IsApproved { get; set; }
    19         [Display(Name = "角色")]
    20         public Role Role { get; set; }
    21     }
    22 }

     然后我们重新编译之后可以看到最终想要的效果了,当然这些都是ASP.NET MVC根据类型自动判断的并选择对应的模板,所以我们也可以直接设置属性使用的模板,这样我们可以通过使用UIHint去指定模板的名称(其实就是视图的名称)。

    2.将元数据用于分布类

    现在开发网站模型都是工具自动生成了,如果按照我们上面的这种方法,一旦重新生成模型了,那么我们就需要重新将注解属性加上上去,既费时又费力。幸好ASP.NET MVC提供了解决方案,我们只需要为那个模型类加上一个分布类即可,比如下面我们将Person的注解属性全部转移到分布类中:

     

    笔者新建了一个名为PersonExt的类:

     1 namespace MvcStudy.Models
     2 {
     3     public class PersonDataBindSource
     4     {
     5         [ScaffoldColumn(false)]
     6         public int PersonId { get; set; }
     7         [Display(Name = "")]
     8         [DataType(DataType.Text)]
     9         public string FirstName { get; set; }
    10         [Display(Name = "")]
    11         [DataType(DataType.MultilineText)]
    12         public string LastName { get; set; }
    13         [Display(Name = "生日")]
    14         [DataType(DataType.DateTime)]
    15         public DateTime BirthDate { get; set; }
    16         public Address HomeAddress { get; set; }
    17         [Display(Name = "是否启用")]
    18         public bool IsApproved { get; set; }
    19         [Display(Name = "角色")]
    20         public Role Role { get; set; }
    21     }
    22 
    23     [MetadataType(typeof(PersonDataBindSource))]
    24     public partial class Person
    25     {
    26     }
    27 }

    然后我们就可以删除Person类的注解属性了,重新编译可以看到最后的输出还是一样的。细心的读者会发现Address属性并没有输出,这是因为辅助器并不会递归查找,所以我们需要在Index视图中写入@Html.EditorFor(x => x.HomeAddress)即可。

     

    3.使用自定义模板

    通过上面的例子我们发现Role呈现出来的是输入框,但实际上应该是选择的,这个时候我们就需要自定义模板,首先我们在Views/Shared下新建一个EditorTemplates文件夹,然后新建一个Role视图,强类型为Role类型,并且不使用母版。然后在视图中写入如下代码:

    1 <select id="Role" name="Role">
    2     @foreach (Role value in Enum.GetValues(typeof(Role)))
    3     {
    4         <option value="@value" @(Model == value ?"selected='selected'":"")>@value</option>
    5     }
    6 </select>

    接着刷新页面,我们就可以看到Role变成了下拉选择了:

    当然文件夹的名称是一种规范,如果需要自定了Display模板,则新建DisplayTemplates文件夹,然后根据类型新建对应名称的视图,当然我们也可以新建一些ASP.NET MVC已经提供了模板的类型,而ASP.NET MVC会首先使用我们的模板而不是自带的。当然我们也可以通过UIHint指定模板。有时候我们需要设置标签的Id,那么我们可以通过ViewData.TemplateInfo.GetFullHtmlFieldId方法获取IdViewData.TemplateInfo.GetFullHtmlFieldName用来获取name,如果你对这些还不够满意,那么你可以通过ViewData.ModelMetadata中的属性获取模型中属性的全部信息。

     

    4.传递参数到模板中

    有时候我们需要在模型模板与模板之间传递自定义的参数,那么下面的方式将可以实现。首先我们在PersonExt文件中给BirthDate属性加上如下的注解属性:

    1 [AdditionalMetadata("val","test")]

    该注解属性的第一个参数是Key,第二个是对应的参数,然后我们在Views/Shared/EditorTemplates中新建一个DateTime视图,并在其中写入如下代码:

     1 @model DateTime
     2 
     3 @{
     4     Layout = null;
     5 }
     6 
     7 @Html.TextBox(ViewData.TemplateInfo.GetFullHtmlFieldName("a"), Model)
     8 @if(ViewData.ModelMetadata.AdditionalValues.ContainsKey("val"))
     9 {
    10     @Html.Label(ViewData.ModelMetadata.AdditionalValues["val"].ToString())
    11 }

    这里ModelMetadataAdditionalValues属性保存了传递的自定义参数,上面我们首先判断是否存在Keyval的参数,然后在将val的值显示出来,重新编译之后刷新页面我们可以看到如下的效果:

  • 相关阅读:
    Hibernate映射Map属性2
    Ajax向Controller发送请求并接受数据需要注意的一个细节
    设置 jsp 表格相邻两行的颜色不一样
    Hibernate映射Map属性
    自己写的爬虫
    在一个jsp页面中引用另一个jsp文件的路径的问题
    state设计原则
    项目图标库怎样选择
    一些有用的插件
    Hook
  • 原文地址:https://www.cnblogs.com/yaozhenfa/p/asp_net_mvc_model_template.html
Copyright © 2020-2023  润新知