MVC DropDownList SelectedValue not displaying correctly

泄露秘密 提交于 2019-11-27 08:52:12

The last argument of the SelectList constructor (in which you hope to be able to pass the selected value id) is ignored because the DropDownListFor helper uses the lambda expression you passed as first argument and uses the value of the specific property.

So here's the ugly way to do that:

Model:

public class MyModel
{
    public int StatusID { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // TODO: obviously this comes from your DB,
        // but I hate showing code on SO that people are
        // not able to compile and play with because it has 
        // gazzilion of external dependencies
        var statuses = new SelectList(
            new[] 
            {
                new { ID = 1, Name = "status 1" },
                new { ID = 2, Name = "status 2" },
                new { ID = 3, Name = "status 3" },
                new { ID = 4, Name = "status 4" },
            }, 
            "ID", 
            "Name"
        );
        ViewBag.Statuses = statuses;

        var model = new MyModel();
        model.StatusID = 3; // preselect the element with ID=3 in the list
        return View(model);
    }
}

View:

@model MyModel
...    
@Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)

and here's the correct way, using real view model:

Model

public class MyModel
{
    public int StatusID { get; set; }
    public IEnumerable<SelectListItem> Statuses { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // TODO: obviously this comes from your DB,
        // but I hate showing code on SO that people are
        // not able to compile and play with because it has 
        // gazzilion of external dependencies
        var statuses = new SelectList(
            new[] 
            {
                new { ID = 1, Name = "status 1" },
                new { ID = 2, Name = "status 2" },
                new { ID = 3, Name = "status 3" },
                new { ID = 4, Name = "status 4" },
            }, 
            "ID", 
            "Name"
        );
        var model = new MyModel();
        model.Statuses = statuses;
        model.StatusID = 3; // preselect the element with ID=3 in the list
        return View(model);
    }
}

View:

@model MyModel
...    
@Html.DropDownListFor(model => model.StatusID, Model.Statuses)

Create a view model for each view. Doing it this way you will only include what is needed on the screen. As I don't know where you are using this code, let us assume that you have a Create view to add a new order.

Create a new view model for your Create view:

public class OrderCreateViewModel
{
     // Include other properties if needed, these are just for demo purposes

     // This is the unique identifier of your order status,
     // i.e. foreign key in your order table
     public int OrderStatusId { get; set; }
     // This is a list of all your order statuses populated from your order status table
     public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}

Order status class:

public class OrderStatus
{
     public int Id { get; set; }
     public string Name { get; set; }
}

In your Create view you would have the following:

@model MyProject.ViewModels.OrderCreateViewModel

@using (Html.BeginForm())
{
     <table>
          <tr>
               <td><b>Order Status:</b></td>
               <td>
                    @Html.DropDownListFor(x => x.OrderStatusId,
                         new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
                         "-- Select --"
                    )
                    @Html.ValidationMessageFor(x => x.OrderStatusId)
               </td>
          </tr>
     </table>

     <!-- Add other HTML controls if required and your submit button -->
}

Your Create action methods:

public ActionResult Create()
{
     OrderCreateViewModel viewModel = new OrderCreateViewModel
     {
          // Here you do database call to populate your dropdown
          OrderStatuses = orderStatusService.GetAllOrderStatuses()
     };

     return View(viewModel);
}

[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
     // Check that viewModel is not null

     if (!ModelState.IsValid)
     {
          viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();

          return View(viewModel);
     }

     // Mapping

     // Insert order into database

     // Return the view where you need to be
}

This will persist your selections when you click the submit button and is redirected back to the create view for error handling.

I hope this helps.

Make Sure that your return Selection Value is a String and not and int when you declare it in your model.

Example:

public class MyModel
{
    public string StatusID { get; set; }
}

For me, the issue was caused by big css padding numbers ( top & bottom padding inside the dropdown field). Basically, the item was being shown but not visible because it was way down. I FIXED it by making my padding numbers smaller.

I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.

I had a property in my ViewData with the same name as the selector for the lambda expression, basically as if you would've had ViewData["StatusId"] set to something.

After I changed the name of the anonymous property in the ViewData the DropDownList helper worked as expected.

Weird though.

My solution was this... Where the current selected item is the ProjectManagerID.

View:

@Html.DropDownList("ProjectManagerID", Model.DropDownListProjectManager, new { @class = "form-control" })

Model:

public class ClsDropDownCollection
{
   public List<SelectListItem> DropDownListProjectManager { get; set; }
   public Guid ProjectManagerID { get; set; }
}

Generate dropdown:

public List<SelectListItem> ProjectManagerDropdown()
{
    List<SelectListItem> dropDown = new List<SelectListItem>();
    SelectListItem listItem = new SelectListItem();

    List<ClsProjectManager> tempList = bc.GetAllProductManagers();           

    foreach (ClsProjectManager item in tempList)
    {
        listItem = new SelectListItem();
        listItem.Text = item.ProjectManagerName;
        listItem.Value = item.ProjectManagerID.ToString();
        dropDown.Add(listItem);
    }
    return dropDown;
}

Please find sample code below.

public class Temp
    {
        public int id { get; set; }
        public string valueString { get; set; }
    }

Controller

public ActionResult Index()
        {
            // Assuming here that you have written a method which will return the list of Temp objects.
            List<Temp> temps = GetList();

            var tempData = new SelectList(temps, "id", "valueString",3);
            ViewBag.Statuses = tempData;

            return View();
        }

View

 @Html.DropDownListFor(model => model.id, (SelectList)ViewBag.Statuses)
    @Html.ValidationMessageFor(model => model.id)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!