2014-02-19 1 views
53

На мой взгляд, у меня есть enumdropdownlist (новая функция в Asp.Net MVC 5.1).Html.EnumDropdownListFor: Показывает текст по умолчанию

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

Если я выполняю вышеуказанный код, я получаю раскрывающийся список для моего следующего перечисления.

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

но по умолчанию я хочу, чтобы мой DropDownList иметь значение (произвольный текст) и это то, что я пытался

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

но теперь проблема, когда я запускаю его, мой DropDownList выглядит это enter image description here Итак, текст по умолчанию, который я хочу показать, по умолчанию не отображается. Если пользователь выбирает «выбрать лицензию» и пытается отправить форму, в ней отображается сообщение об ошибке «выберите лицензию», но оно не отображается как текст по умолчанию. Что-то мне нужно изменить?

Пс: Изображение представляет собой скриншот страницы при загрузке. По умолчанию он отобразит пробную версию как выбранную опцию.

+1

Ответ Майкл Ричардсон должен быть действительно правильный ответ. –

ответ

68

Попробуйте изменить Index из LicenseTypes отталкиваться от 1 не 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) 
+0

, который будет работать, но затем он добавит 'Выбрать лицензию' как одно из значений перечисления с идентификатором 0. Я хочу иметь возможность показывать сообщение об ошибке, когда пользователь не выбирает одно из значений из перечисления. – Cybercop

+0

может это сделать, но я оставлю его неприемлемым в течение некоторого времени и посмотрю, сможет ли кто-нибудь прийти с лучшим решением, до тех пор +1 для идеи ура. – Cybercop

+2

@probackpacker имеет лучший ответ, этот вариант не попадает в обработку валидации. – Dan

60

К тому времени, когда отображается ваш EnumDropDownListFor, SelectedLicense уже имеет значение по умолчанию для типа 0.

Просто измените тип вашего SelectedLicense собственности обнуляемого перечисления, например:

public LicenseTypes? SelectedLicense { get; set; } 

Это также позволяет продолжать использовать атрибут Required, который я считаю значительно чище. Атрибут Required не даст нулевого ответа, поэтому, даже если ваша модель допускает null, форма не будет.

+1

Я думаю, что это лучший ответ на сегодня, но он выглядит как взломанный. Реальное исправление должно находиться внутри MVC для правильной обработки непустых Enums. – jhilden

+2

@jhilden, я думаю, что MVC _is_ обрабатывает ненулевое Enum правильно, делая _exactly_ то, что вы говорите ему. В .NET переменные enum всегда инициализируются значением 0] (http://stackoverflow.com/a/529937/1812515).Предположим, что вы оставили тип свойства как недействительный Enum ('LicenseTypes'), и форма была опубликована с помощью« Выбрать лицензию »(элемент списка без значения). Свойству 'SelectedLicense' будет присвоено значение по умолчанию (' Trial'). Если бы вы только что изучили модель, это было бы неотличимо от пользователя, фактически выбирающего значение «Trial». –

+0

Вы правы. Я оглянулся на свой другой код и, если мы хотим, чтобы int требовался, но не имел значения по умолчанию, мы делаем следующее: [обязательно] public int? NullableIntHere {get; set;} – jhilden

13

У меня есть перечисление:

public enum Sex 
{ 
    Male, 
    Female 
} 

В моей модели у меня есть:

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

An в представлении:

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

необходим класс ViewModel, чтобы иметь значение по умолчанию, установленное на свойстве перечислений для того, чтобы быть по умолчанию выбран общественного

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

Am Я немного опоздал?

Изменение значений типа перечисления не очень удовлетворительно.

Ни одно из них не меняет свойство модели, чтобы сделать его нулевым, а затем добавить атрибут [Обязательный], чтобы он не мог быть нулевым.

Я предлагаю использовать ViewBag, чтобы установить выбранное по умолчанию выпадающее меню. Линия 4 контроллера, приведенная ниже, является единственной важной.

EDIT: Ах ... новичками ... Моя первая идея состояла в том, чтобы использовать 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..."

+0

@shim: он работает с частичным видом, вызывается с основного вида, но не в частичном разрешении, вызываемом в AJAX. Частичные виды получают копию основного вида ViewBag. Выполнение действия индекса, когда частичный вид вызывается основным видом. Вы не делаете, когда запрос AJAX вызывает частичное представление. Index.cshtml: – Rikou