【问题标题】:Html.EnumDropdownListFor: Showing a default textHtml.EnumDropdownListFor:显示默认文本
【发布时间】:2014-02-19 11:06:26
【问题描述】:

在我看来,我有一个 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"})

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

Ps:图片是页面加载时的截图。默认情况下,它会将试用显示为选定选项。

【问题讨论】:

    标签: c# asp.net-mvc drop-down-menu asp.net-mvc-5.1


    【解决方案1】:

    尝试将LicenseTypesIndex1改为0,如下所示:

    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 的枚举值之一。当用户未从枚举中选择其中一个值时,我希望能够显示错误消息.
    • 可以这样做,但我会暂时不接受它,看看是否有人能提供更好的解决方案,直到那时为你的想法 +1。
    • @probackpacker 有更好的答案,这个选项不会在验证处理中被捕获
    【解决方案2】:

    当您的EnumDropDownListFor 被渲染时,SelectedLicense 已经具有该类型的默认值,即0

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

    public LicenseTypes? SelectedLicense { get; set; }
    

    这也允许您继续使用Required 属性,我认为它明显更干净。 Required 属性不允许空响应,因此即使您的模型允许空值,表单也不会。

    【讨论】:

    • 我认为这是今天最好的答案,但似乎是一个 hack。真正的修复应该在 MVC 中正确处理不可为空的枚举。
    • @jhilden,我认为 MVC is 通过执行 exactly 您告诉它的操作来正确处理不可为空的枚举。在 .NET 中enum variables are always initialized to the value 0。假设您将属性类型保留为不可为空的枚举 (LicenseTypes),并且在发布表单时选择了“选择许可证”(没有值的列表项)。您的 SelectedLicense 属性最终会使用默认值 (Trial)。如果您只是检查模型,则与实际选择 Trial 值的用户无法区分。
    • 你是对的。我回顾了我的其他代码,如果我们想要一个 int 但没有默认值,那么我们这样做:[required] public int? NullableIntHere {get;set;}
    【解决方案3】:

    我有一个枚举:

    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" })
    

    【讨论】:

      【解决方案4】:

      ViewModel 类需要在 enum 属性上设置默认值,才能使其成为默认选择 公开的

      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>
      }
      

      【讨论】:

        【解决方案5】:

        我是不是有点晚了?

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

        两者都没有更改模型属性以使其可以为空,然后添加一个 [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
        }
        

        Without the "ModelState.SetModelValue or ViewBag.FavouriteMusic = string.Empty" line in the model Index action the default selected value would be "Metal" and not "Select your music..."

        【讨论】:

        • @shim:它适用于从主视图调用的局部视图,但不适用于在 AJAX 中调用的局部视图。部分视图获取主视图 ViewBag 的副本。当主视图调用局部视图时,您确实会执行索引操作。当 AJAX 请求调用局部视图时,您不会这样做。索引.cshtml:
        猜你喜欢
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 2013-12-14
        • 2019-01-17
        • 1970-01-01
        • 2017-12-04
        • 2014-02-03
        • 1970-01-01
        相关资源
        最近更新 更多