How do I make a DropDownList linked with a model property?

4

I have my class:

public class Topico
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public string Observacao { get; set; }
}

and my SubTopic class

public class SubTopico
{
    public int Id { get; set; }
    public virtual Topico Topico { get; set; }
    public int? TopicoId { get; set; }
    public string Nome { get; set; }
    public string Observacao { get; set; }
}

In my controller I have:

public ActionResult Create()
{
    ViewBag.Topico = new SelectList(db.Topicoes, "Id", "Nome");
    return View();
}

And in my view I have my DropDownList

 @Html.DropDownList("Topico",string.Empty)

Until then it loads all topics, etc.

But I can not do a Bind on it when saving. In my action to Save

public ActionResult Create([Bind(Include="Id,Topico,Nome,Observacao")] SubTopico subtopico)
{
    if (ModelState.IsValid)
    {
        subtopico.TopicoId = Convert.ToInt32(Request.Params["Topico"]);
        db.SubTopicoes.Add(subtopico);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(subtopico);
}

It does not come from the Topic Id, because the class is null. So I capture using Request.Params["Topico"];

How do I link my dropdownlist with my public virtual Topico property that I have in my SubTopic class

    
asked by anonymous 27.05.2014 / 23:47

4 answers

9

The way you did, the first time the questioning, would be like this:

public ActionResult Create()
{
    ViewBag.Topico = new SelectList(db.Topicoes, "Id", "Nome");
    return View();
}

In View:

@Html.DropDownList("TopicoId", ViewBag.Topico as SelectList)

or

@Html.DropDownListFor(model => model.TopicoId, ViewBag.Topico as SelectList)
    
28.05.2014 / 05:27
4

Use @DropDownListFor :

@Html.DropDownList(model => model.TopicoId, ((IEnumerable)ViewBag.Topicos).Select(option => new SelectListItem {
    Text = option.Nome, 
    Value = option.Id.Value, 
    Selected = (Model != null) && (option.Id == (int)Model.TopicoId ?? 0)
}, "Selecione..."))

So you do not have to use Request.Params , which is not exactly secure.

In this case of POST , Topico will even be null. It loads into data selection, such as if you drill down Subtopico using

context.Subtopicos.Include(st => st.Topico).FirstOrDefault();

Finally, you can simplify your Controller to:

public ActionResult Create([Bind(Include="Id,TopicoId,Nome,Observacao")] SubTopico subtopico)
{
    if (ModelState.IsValid)
    {
        db.SubTopicoes.Add(subtopico);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(subtopico);
}
    
27.05.2014 / 23:54
3

One simple way I found and got was:

In my controller, return a list:

ViewBag.Topicos = db.Topicoes.ToList();

And in my View use DropDownlistFor as follows.

@Html.DropDownListFor(model => model.TopicoId, new SelectList(ViewBag.Topicos,"Id","Nome","Selecione..."))
    
28.05.2014 / 04:26
2

You can also use SQL query as a data source for DropDownList:

No Controller:

public ActionResult NomeDaAction() {
    ViewBag.DadosDropDown = (from c in db.Tabela select c.ColunaDaTabela).Distinct();
    Return View();
}

No View:

@Html.DropDownListFor(model => model.CampoOndeArmazenar, new SelectList(ViewBag.DadosDropDown, "Coluna1DaTabela", "OutraColunaDaTabela"), htmlAttributes: new { @class = "ClasseCSSdoDropDownList" })

In the view, if you do not want to assign a CSS class to the checkbox, just remove the htmlAttributes command as below:

@Html.DropDownListFor(model => model.CampoOndeArmazenar, new SelectList(ViewBag.DadosDropDown, "Coluna1DaTabela", "OutraColunaDaTabela"))
    
23.07.2014 / 20:53