65.9K
CodeProject 正在变化。 阅读更多。
Home

在 MVC 5.1 中处理枚举

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (36投票s)

2014年5月23日

CPOL

5分钟阅读

viewsIcon

131151

了解如何在 Asp.Net MVC 5.1 中处理枚举下拉列表

引言

Enum

如果您正在阅读这篇文章,我敢打赌您至少有一次去 #stackoverflow 寻找解决您遇到的难题的方法。前几天,我在 #stackoverflow 上浏览时,注意到不少开发人员在处理 Asp.Net MVC 中的枚举时经常遇到困难,他们的代码量不足以将枚举转换为下拉列表。这个问题已经存在很多年了。显然,聪明的开发人员并没有袖手旁观。他们找到了处理这个问题的不同方法,而这些方法通常并不容易遵循。

随着 MVC 5.1 于 2014 年 2 月 27 日发布,终于有了视图中的枚举支持。老式的做法仍然适用且可用,并且可以在网上找到大量的相关资源,但不推荐,因为新方法更简单。我不会讨论旧的方法,而是专注于实现我们目标的新方法。

软件要求

您将需要以下任何一项:

  • Visual Studio 2012:下载适用于 Visual Studio 2012 的 ASP.NET 和 Web 工具 2013.1。
  • Visual Studio 2013:下载 Visual Studio 2013 更新 1。需要此更新才能编辑 ASP.NET MVC 5.1 Razor 视图。

现在,您已经拥有了这些工具,让我们开始创建一个 Asp.Net Web 应用程序。为了演示枚举支持,我们将构建一个简单的学生注册表单,其中我们期望一个下拉框显示性别、国家等信息供人们选择。最初,为了演示目的,我已经创建了以下架构。您可以从这里下载整个源代码文件。

EnumDemo_Project Hierarchy
Gender 枚举非常简单,它包含 Male 和 Female,定义如下:
public enum Gender
{
     Male,
     Female
}

枚举列表中添加了 5 个国家。Country 枚举定义如下:

    public enum Country
    {
        Australia,
        Bangladesh,
        England,
        France,
        Usa
    }

学生实体 [POCO(普通 C# 对象)类] 看起来是这样的:

    public class Student
    {
        public int Id { get; set; }
        public String Name { get; set; }
        public Gender Gender { get; set; }
        public Country Country { get; set; }
    }

目前,如果我们仅依靠脚手架来完成繁重的工作并生成一些视图,那么您最终会得到这样的结果:

如果您以前从未处理过枚举,这个视图可能会让您感到恐慌,您可能会说:

嘿,等等,脚手架不起作用!它没有正确渲染视图

现在您可能想检查脚手架为视图生成的代码,这里是:

    <div class="form-group">
            @Html.LabelFor(model => model.Gender, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Gender)
                @Html.ValidationMessageFor(model => model.Gender)
            </div>
        

        <div class="form-group">
            @Html.LabelFor(model => model.Country, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Country)
                @Html.ValidationMessageFor(model => model.Country)
            </div>
        </div>

一切看起来都很正常,对吧?您在正确的位置使用了 EditorFor() 编辑器扩展,并且数据也正确传递了。那么问题出在哪里呢?好吧,实际上 EditorFor() 不知道如何渲染枚举,所以它使用默认设置并为枚举渲染一个文本框。

不要恐慌!我们很快就会处理这个问题。但首先,请通过 NuGet 更新Microsoft ASP.NET MVC。否则您将找不到我们将用于解决问题的扩展方法。

Managing NuGet Packages 管理 NuGet 包[/caption] 完成后,将标记更改为如下所示:
     @*@Html.EditorFor(model => model.Gender)*@

     @Html.EnumDropDownListFor(model=>model.Gender)

在这里,我们使用了新的 EnumDropDownListFor() 扩展方法。实现与 EditorFor() 扩展相同。万岁!一行代码就解决了问题。

EnumDemo_4

现在,让我们稍微扩展一下场景。如果我们想在 enumdropdowlist 中显示特殊字符/符号空格怎么办?我们知道枚举不支持空格/特殊字符,所以我们可以使用Display Attribute。在以下场景中,我们使用 [Display(Name="United States")] 来显示“United States”,而不是显示“Usa”。

   public enum Country
    {
        Australia,
        Bangladesh,
        England,
        France,
        [Display(Name="United States")]
        Usa
    }
这是视图。您可以看到 EnumDropDownList 中显示“United States”。

EnumDemo_5

注意:此时,如果您创建一个新学生并从 EnumDropDownList 中选择值,当您重新访问以查看您刚刚保存的内容时,您会发现列表中显示的不是“United States”,而是“Usa”。如果您还不明白我的意思,请看下图。

而这正是我们可能不想显示的内容。为了解决这个问题,我们可以使用某种模板机制。

我们将提供枚举模板,重要的是将其放在正确的文件夹中,因为我们希望所有枚举默认都使用此模板。这是我们将为显示场景创建部分视图的位置/Shared/DisplayTemplates ,请确保将其命名为enum.cshtml。文件层次结构如下图所示:

EnumDemo_8

在 Enum.cshtml 中复制以下代码,您就完成了!

@model Enum

@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    // Display Enum using same names (from [Display] attributes) as in editors
    string displayName = null;
    foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata, (Enum)Model))
    {
        if (item.Selected)
        {
            displayName = item.Text ?? item.Value;
        }
    }

    // Handle the unexpected case that nothing is selected
    if (String.IsNullOrEmpty(displayName))
    {
        if (Model == null)
        {
            displayName = String.Empty;
        }
        else
        {
            displayName = Model.ToString();
        }
    }

    @Html.DisplayTextFor(model => displayName)
}
else
{
    // This Enum type is not supported.  Fall back to the text.
    @Html.DisplayTextFor(model => model)
}

再次运行应用程序,您将在屏幕上找到您久违的解决方案:)

如果您还记得,我们对脚手架生成的代码做了一些更改。如果您正在处理一个大型应用程序,其中几乎每个视图都处理枚举值,那么在多个地方进行更改可能会很困难且耗时。在这种情况下,我倾向于编写 EditorTemplates,以便脚手架生成的代码能够顺利运行,而无需进行任何修改。

这是我们将为显示场景创建部分视图的位置/Shared/EditorTemplates,请确保将其命名为enum.cshtml。文件层次结构如下图所示:

EnumDemo_9

在 Enum.cshtml 中复制以下代码,您就可以使用脚手架生成的代码了。

@model Enum

@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    @Html.EnumDropDownListFor(model => model, htmlAttributes: new { @class = "form-control" })
}
else
{
    @Html.TextBoxFor(model => model, htmlAttributes: new { @class = "form-control" })
}

这就是您在 MVC5 中处理枚举所需了解的一切。希望这篇文章对您有所帮助 :) 。

附加资源


© . All rights reserved.