Html.EnumDropdownListFor:显示默认文本


67

在我看来,我有一个enumdropdownlist(Asp.Net MVC 5.1中的一项新功能)。

@Html.EnumDropDownListFor(m => m.SelectedLicense,new { @class="form-control"})

如果执行上面的代码,我将得到以下枚举的下拉列表。

public enum LicenseTypes
{
    Trial = 0,
    Paid = 1
}

但默认情况下,我希望我的下拉列表具有一个值(自定义文本),这就是我尝试的

@Html.EnumDropDownListFor(m => m.SelectedLicense,"Select a license" ,new { @class="form-control"})

但是现在的问题是,当我运行它时,我的下拉列表看起来像这样, 在此处输入图片说明 因此,我要显示的默认文本在默认情况下不会出现。如果用户选择“选择许可证”并尝试提交表单,则确实会显示“选择许可证”错误,但不会显示为默认文本。我需要改变什么?

附:图像是页面加载时的屏幕截图。默认情况下,它将显示“试用”作为选定选项。

Answers:


88

尝试改变IndexLicenseTypes,从开始10象下面这样:

public enum LicenseTypes
{
    Trial = 1,
    Paid = 2
}

然后,您可以Range attribute用来验证所选的许可证类型,如下所示:

public class YourViewModel
{
     //Other properties
     [Range(1,int.MaxValue,ErrorMessage = "Select a correct license")]
     public LicenseTypes LicenseTypes { get; set; }
}

最后,您认为:

   @Html.EnumDropDownListFor(m => m.LicenseTypes,"Select a license",new { @class = "form-control"})
   @Html.ValidationMessageFor(m => m.LicenseTypes)

可以,但是它将添加Select a license为ID为0的枚举值之一。当用户未从枚举中选择值之一时,我希望能够显示错误消息。
Cyber​​cop

可以做到这一点,但我会在一段时间内不予接受,看看是否有人可以提供更好的解决方案,直到您+1为止。
Cyber​​cop

2
@probackpacker有更好的答案,此选项将不会在验证处理中被发现
Dan

72

到您EnumDropDownListFor的渲染时SelectedLicense,该类型的默认值已经为0

只需将SelectedLicense属性的类型更改为可为空的枚举即可,如下所示:

public LicenseTypes? SelectedLicense { get; set; }

这也使您可以继续使用该Required属性,我认为该属性更加简洁。该Required属性将不允许null响应,因此即使您的模型允许null,该表单也不允许。


1
我认为这是今天最好的答案,但似乎是一个hack。真正的修复应该在MVC内,以正确处理不可为空的枚举。
jhilden 2014年

3
@jhilden,我认为MVC做正确处理非空的枚举正是你告诉它做什么。在.NET中,枚举变量始终被初始化为值0。假设您将属性类型保留为不可为空的Enum(LicenseTypes),并且表单在发布时选择了“选择许可证”(无值的列表项)。您的SelectedLicense媒体资源将以默认值(Trial)结尾。如果您只是检查模型,则与实际选择Trial值的用户是无法区分的。
Michael Richardson

你是对的。我回头看了一下我的其他代码,如果我们想要一个int,但没有默认值,那么我们做:[required] public int?NullableIntHere {get; set;}
jhilden 2014年

16

我有一个枚举:

public enum Sex
{
    Male,
    Female
}

在我的模型中,我有:

    [DisplayName("Sex")]
    [Required]
    public Sex? Sex { get; set; }

在视图中:

    @Html.EnumDropDownListFor(model => model.Sex, "Select sex", new { @class = "form-control", type = "text"})

这样,我有一个带有默认选项“选择性别”的下拉列表,但是验证仅接受枚举提供的选项(“男”和“女”)。

在MVC3中(没有EnumDropDownListFor),我在模型中使用了:

    [DisplayName("Sex")]
    [Required(AllowEmptyStrings=false)]
    public Sex? Sex { get; set; }

    Sex = null;

    Sexes = Repository.GetAutoSelectList<Sex>("");

鉴于:

    @Html.DropDownListFor(model => model.Sex, Model.Sexes, new { @class = "form-control", type = "text" })

10

ViewModel类需要在enum属性上设置默认值,使其成为默认的选定public

public class Test
    {
        public Cars MyCars { get; set; }
        public enum Cars
        {
            [Display(Name = @"Car #1")]
            Car1 = 1,
            [Display(Name = @"Car #2")]
            Car2 = 2,
            [Display(Name = @"Car #3")]
            Car3 = 3
        }

    }

控制器:

 public class EnumController : Controller
    {
        // GET: Enum
        public ActionResult Index()
        {
            var model = new Test {MyCars = Test.Cars.Car3}; // set default value
            return View(model);
        }
        [HttpPost]
        public ActionResult Index(Test model)
        {
            .....
        }
    }

视图:

@Html.BeginForm()
{
<div class="panel bg-white">
    <div class="panel-header fg-white">
        Enums
    </div>
    <div class="panel-content">
        <div class="input-control select size3">
            @Html.EnumDropDownListFor(model => model.MyCars)

        </div>
    </div>
    <input type="submit" class="button success large" />
</div>
}

0

我来晚了吗?

更改枚举类型的值不是很令人满意。

都没有更改模型属性以使其可为空,然后添加[Required]属性以防止其为可空。

我建议使用ViewBag设置下拉菜单的默认选定值。 控制器下面的第4行是唯一重要的。

编辑:啊...新手...我的第一个想法是使用ModelState.SetModelValue,因为我的新手本能阻止我简单地尝试在ViewBag中设置所需的值,因为下拉列表已绑定到模型。我肯定有一个问题:它将绑定到模型的属性,而不是ViewBag的属性。我全错了:ViewBag没问题。我更正了代码。

这是一个例子。

模型:

namespace WebApplication1.Models {

    public enum GoodMusic {
        Metal,
        HeavyMetal,
        PowerMetal,
        BlackMetal,
        ThashMetal,
        DeathMetal // . . .
    }

    public class Fan {
        [Required(ErrorMessage = "Don't be shy!")]
        public String Name { get; set; }
        [Required(ErrorMessage = "There's enough good music here for you to chose!")]
        public GoodMusic FavouriteMusic { get; set; }
    }
}

控制器:

namespace WebApplication1.Controllers {
    public class FanController : Controller {
        public ActionResult Index() {
            ViewBag.FavouriteMusic = string.Empty;
            //ModelState.SetModelValue( "FavouriteMusic", new ValueProviderResult( string.Empty, string.Empty, System.Globalization.CultureInfo.InvariantCulture ) );
            return View( "Index" );
        }
        [HttpPost, ActionName( "Index" )]
        public ActionResult Register( Models.Fan newFan ) {
            if( !ModelState.IsValid )
                return View( "Index" );
            ModelState.Clear();
            ViewBag.Message = "OK - You may register another fan";
            return Index();
        }
    }
}

视图:

@model WebApplication1.Models.Fan
<h2>Hello, fan</h2>
@using( Html.BeginForm() ) {
    <p>@Html.LabelFor( m => m.Name )</p>
    <p>@Html.EditorFor( m => m.Name ) @Html.ValidationMessageFor( m => m.Name )</p>
    <p>@Html.LabelFor( m => m.FavouriteMusic )</p>
    <p>@Html.EnumDropDownListFor( m => m.FavouriteMusic, "Chose your favorite music from here..." ) @Html.ValidationMessageFor( m => m.FavouriteMusic )</p>
    <input type="submit" value="Register" />
    @ViewBag.Message
}

如果模型索引操作中没有“ ModelState.SetModelValue或ViewBag.FavouriteMusic = string.Empty”行,则默认选择的值为“ Metal”而不是“ Select your music ...”


@shim:它适用于从主视图调用的局部视图,但不适用于AJAX中调用的局部视图。局部视图获取主视图ViewBag的副本。当主视图调用部分视图时,您确实执行Index操作。当AJAX请求调用局部视图时,您不需要。Index.cshtml:
Rikou
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.