DropDownListFor in a for

2

I am trying to fill a DropDownList with a selected value within a for , but it is not working properly. What happens is that when Action Index returns the model to View , values are not being selected, always being the first item of DropDownList selected.

I've put together a small example to make it easier.

  

I edited by adding @RichardDay's suggestions

     

To help, I've committed to GitHub link

Classes

public class Principal
{
    public MeuEnum Item { get; set; }
    public List<Teste> Teste { get; set; }
}

    public class Teste
    {
        public MeuEnum item { get; set; }
    }

    public enum MeuEnum
    {
        Item0 = 0,

        Item1 = 1,

        Item2 = 2,

        Item3 = 3,

        Item4 = 4,

        Item5 = 5,

        Item6 = 6,

        Item7 = 7,

        Item8 = 8,
    }

    public static class Helpers
    {
        public static SelectList MeuEnumItens(this HtmlHelper html)
        {
            var item0 = new SelectListItem() { Value = "Item0", Text = "0" };
            var item1 = new SelectListItem() { Value = "Item1", Text = "1" };
            var item2 = new SelectListItem() { Value = "Item2", Text = "2" };
            var item3 = new SelectListItem() { Value = "Item3", Text = "3" };
            var item4 = new SelectListItem() { Value = "Item4", Text = "4" };
            var item5 = new SelectListItem() { Value = "Item5", Text = "5" };
            var item6 = new SelectListItem() { Value = "Item6", Text = "6" };
            var item7 = new SelectListItem() { Value = "Item7", Text = "7" };
            var item8 = new SelectListItem() { Value = "Item8", Text = "8" };

            return new SelectList(new[] { item0, item1, item2, item3, item4, item5, item6, item7, item8 }, "Value", "Text");
        }
    }

Controller

 public class HomeController : Controller
{
    public ActionResult Index()
    {
        Principal p = new Principal()
        {
            Item = MeuEnum.Item6
        };
        p.Teste = new List<Teste>();

        p.Teste.Add(new Teste() { item = MeuEnum.Item0 });
        p.Teste.Add(new Teste() { item = MeuEnum.Item1 });
        p.Teste.Add(new Teste() { item = MeuEnum.Item2 });
        p.Teste.Add(new Teste() { item = MeuEnum.Item3 });

        return View(p);
    }
}

View

    @model TesteDropDownEnum.Controllers.Principal
@using TesteDropDownEnum.Controllers
@{
    ViewBag.Title = "Home Page";
}

<!--Assim funciona-->
@Html.DropDownListFor(a => a.Item, Html.MeuEnumItens(), "Selecione", htmlAttributes: new { @class = "form-control", @readonly = "readonly" })

@using (Html.BeginForm())
{
    for (int i = 0; i < Model.Teste.Count(); i++)
    {
        <div class="row form-group">
            <div class="col-md-12">
                <label>Origem da Mercadoria @Model.Teste[i].item</label>
                <!--Assim não funciona-->
                @Html.DropDownListFor(a => a.Teste[i].item, Html.MeuEnumItens(Model.Teste[i].item), "Selecione", htmlAttributes: new { @class = "form-control", @readonly = "readonly" })
            </div>
        </div>
    }
}
    
asked by anonymous 29.12.2015 / 14:44

1 answer

2

The SelectListItem object has a Selected property. if it is set to true , this item will be selected. If no item has a true value for this property, the value selected is the optionalLabel parameter of DropDownListFor , if it exists. In the example below I modified and set it to "Select". You making this the problem of always coming the first selected should end.

@Html.DropDownListFor(a => a.Teste[i].item, Html.MeuEnumItens(), "Selecione", htmlAttributes: new { @class = "form-control", @readonly = "readonly" })

It would be interesting if your MeuEnumItens method would accept one more optional parameter ( MeuEnum? valorSelecionado ) and perform the comparison to set the value of the Selected property of the 'SelectListItem' object. I took advantage of and left a hint on how to modify the creation of enumerator selectlists.

public static IEnumerable<SelectListItem> MeuEnumItens(this HtmlHelper html, MeuEnum? itemSelecionado)
{
    var lista = new List<SelectListItem>();

    foreach (MeuEnum item in System.Enum.GetValues(typeof(MeuEnum)))
    {
        lista.Add(new SelectListItem() { Text = item.ToString("F"), Value = item.ToString(), Selected = (itemSelecionado.HasValue ? itemSelecionado.Value == item : false) });
    }

    return lista;
}

Finally, use BeginCollectionItem to dynamically generate the DropDowns list, with the correct binding :

Index.cshtml

foreach (var teste in Model.Testes)
{
    @Html.Partial("_Item", teste)
}

_Item.cshtml

@model TesteDropDownEnum.Controllers.Teste
@using TesteDropDownEnum.Controllers

@using (Html.BeginCollectionItem("Testes"))
{
    <div class="row form-group">
        <div class="col-md-12">
            <label>Origem da Mercadoria @Model.item</label>
            @Html.DropDownListFor(model => model.item, Html.MeuEnumItens(Model.item), "Selecione", htmlAttributes: new { @class = "form-control", @readonly = "readonly" })
        </div>
    </div>
}
    
29.12.2015 / 15:09