c# - mvc - Html.EnumDropdownListFor: muestra un texto predeterminado
selectlistitem mvc dropdownlist (5)
En mi opinión, tengo una lista enumdowndown (una nueva característica en Asp.Net MVC 5.1).
@Html.EnumDropDownListFor(m => m.SelectedLicense,new { @class="form-control"})
Si ejecuto el código anterior, obtengo una lista desplegable para mi siguiente enumeración.
public enum LicenseTypes
{
Trial = 0,
Paid = 1
}
pero por defecto quiero que mi lista desplegable tenga un valor (texto personalizado) y esto es lo que probé
@Html.EnumDropDownListFor(m => m.SelectedLicense,"Select a license" ,new { @class="form-control"})
pero ahora el problema es cuando lo ejecuto, mi lista desplegable se parece a esto Por lo tanto, el texto predeterminado que quiero mostrar no aparece de forma predeterminada. Si un usuario selecciona "seleccionar una licencia" e intenta enviar el formulario, muestra un error que dice "seleccionar una licencia" pero no se muestra como texto predeterminado. Algo que necesito cambiar?
Ps: la imagen es la captura de pantalla de la página cuando se carga. Por defecto, mostrará la opción de prueba como seleccionada.
Intente cambiar el Index
de LicenseTypes
desde 1
no como el siguiente:
public enum LicenseTypes
{
Trial = 1,
Paid = 2
}
Luego puede usar el Range attribute
para validar el tipo de licencia seleccionado como se muestra a continuación:
public class YourViewModel
{
//Other properties
[Range(1,int.MaxValue,ErrorMessage = "Select a correct license")]
public LicenseTypes LicenseTypes { get; set; }
}
Finalmente, en su opinión:
@Html.EnumDropDownListFor(m => m.LicenseTypes,"Select a license",new { @class = "form-control"})
@Html.ValidationMessageFor(m => m.LicenseTypes)
La clase ViewModel necesita tener el valor predeterminado establecido en la propiedad enum para que sea el público seleccionado predeterminado
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
}
}
Controlador:
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)
{
.....
}
}
Ver:
@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>
}
Tengo una enumeración:
public enum Sex
{
Male,
Female
}
En mi modelo tengo:
[DisplayName("Sex")]
[Required]
public Sex? Sex { get; set; }
Un en la vista:
@Html.EnumDropDownListFor(model => model.Sex, "Select sex", new { @class = "form-control", type = "text"})
Con esto, tengo un menú desplegable con la opción predeterminada "Seleccionar sexo", pero la validación solo acepta las opciones proporcionadas por enum ("Hombre" y "Mujer").
En MVC3 (sin EnumDropDownListFor) que utilicé en el modelo:
[DisplayName("Sex")]
[Required(AllowEmptyStrings=false)]
public Sex? Sex { get; set; }
Sex = null;
Sexes = Repository.GetAutoSelectList<Sex>("");
En vista:
@Html.DropDownListFor(model => model.Sex, Model.Sexes, new { @class = "form-control", type = "text" })
¿Estoy un poco tarde?
Cambiar los valores del tipo enum no es muy satisfactorio.
Tampoco está cambiando la propiedad del modelo para convertirlo en nulo y luego agregar un atributo [Obligatorio] para evitar que sea nulo.
Propongo usar ViewBag para establecer el valor seleccionado predeterminado del menú desplegable. La línea 4 del controlador justo debajo es la única importante.
EDITAR: Ah ... novatos ... Mi primera idea fue usar ModelState.SetModelValue porque mi instinto de novato me impidió simplemente intentar establecer el valor deseado en ViewBag ya que el menú desplegable estaba vinculado al modelo. Estaba seguro de tener un problema: se uniría a la propiedad del modelo, no a la propiedad del ViewBag. Estaba equivocado: ViewBag está bien. Corregí el código.
Aquí hay un ejemplo.
Modelo:
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; }
}
}
Controlador:
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();
}
}
}
Ver:
@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
}
Para cuando se represente EnumDropDownListFor
SelectedLicense
ya tiene el valor predeterminado para el tipo, que es 0
.
Simplemente cambie el tipo de su propiedad SelectedLicense
a una enumeración nullable, así:
public LicenseTypes? SelectedLicense { get; set; }
Esto también le permite continuar usando el atributo Required
, que creo que es significativamente más limpio. El atributo Required
no permitirá una respuesta nula, por lo tanto, aunque su modelo permita valores nulos, el formulario no lo hará.