What is the best ways to bind @Html.DropDownListFor in ASP.NET MVC5?
Asked Answered
P

2

5

I want to bind @Html.DropDownListFor from Model data without using Viewbag and look at many different examples on the web. But most of them use Viewbag or an extension method and I want a better approach to solve this problem. I tried the the following methods but it does not seem to work:

@Html.DropDownListFor(m => m.LabId, new SelectList(Model.Lab, "Id", "Name"), 
    "---- Select----", new { @class = "selectpicker" } )

Is it possible to bind @Html.DropDownListFor directly from Model without using Viewbag or any extra method in the Controller in ASP.NET MVC5? Could you please give some examples to perform this best?

Providing answered 17/9, 2016 at 19:20 Comment(1)
ViewBag is just a container -- pass whatever data you need as a strongly typed @modelStoffel
P
7

The strongly typed view model approach which does not use dynamic stuff like ViewBag

You can add a new property to your view model for the SELECT options of type IEnumrable<SelectListItem>.

view model is a simple POCO class used to transfer data between view to action method and vice versa. They are specific to the views. Add properties only needed for the view.

public class CreateUserVm
{
   public IEnumrable<SelectListItem> Labs { set;get;}
   public int SelectedLabId { set;get;}
   //Add other properties as needed for the view
}

and in your GET action, create an object of this view model, load the Labs property and send that to the view.

public ActionResult Create()
{
  var vm= new CreateUserVm();
  // Hard coded for demo. You can replace with real data from db
  vm.Labs = new List<SelectListItem> {
     new SelectListItem { Value="1", Text="One" },
     new SelectListItem { Value ="2", Text="Two" }
  };
  return View(vm);
}

and in the view which is strongly typed to this view model, call the DropDownListFor helper method

@model CreateUserVm
@Html.DropDownListFor(f=>f.SelectedLabId, Model.Labs,"Select one")

Pre-selecting an option in the dropdown

If you like to pre select one option when razor renders the page, You can set the SelectedLabId property value of your view model to the value property value of of the Option item(SelectListItem).

public ActionResult Create()
{
  var vm= new CreateUserVm();
  // Hard coded for demo. You can replace with real data from db
  vm.Labs = new List<SelectListItem> {
     new SelectListItem { Value="1", Text="SugarLab" },
     new SelectListItem { Value ="2", Text="CandyLab" },
     new SelectListItem { Value ="3", Text="SodaLab" }
  };
  vm.SelectedLabId = 2; // Will set "CandyLab" option as selected
  return View(vm);
}

If you want to use real data, instead of the hard coded 2 items, you can do this

vm.Labs = dbContext.Labs.Select(x=>new SelectListItem { Value=x.Id.ToString(),
                                                        Text= x.Name }).ToList();

Assuming dbContext is your DbContext class object and it has a Labs property of type DbSet<Lab> where each Lab entity has an Id and Name property.

Placket answered 17/9, 2016 at 19:25 Comment(2)
Many thanks for your detailed explanations and answer. I think this is the cleanest way for populating Dropdownlist.Providing
There's a fine distinction between default and selected value when it comes to DropDownListFor, and I would argue that your method of pre-selecting the value is not entirely correct - you'd better use one of the DropDownListFor parameters for that rather than setting it on the model. I wrote a short article just on that problem - nimblegecko.com/…Riata
T
0

You are on a good track by having the list items in your model. I don't know how you have implemented that in your code.

The Lab property in your model class should be an IEnumerable, List or Collection of what you want. and then in your razor view, the looks fine.

Perhaps what you're forgetting is to initialise the list from the action method in the controller before sending it to the view. E.g:

var model = new ViewModel{

Labs = repository.GetLabs();
}

Above i assume the repository should be something that has access or means of getting the needed data, and also that the Labs property is defined as IEnumerable<Lab> Labs in the ViewModel class.

All should work. Perhaps you should be clear as to what error you're getting.

Tybie answered 17/9, 2016 at 19:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.