MVC DropDownList SelectedValue not displaying correctly
Asked Answered
B

7

25

I tried searching and didn't find anything that fixed my problem. I have a DropDownList on a Razor view that will not show the the item that I have marked as Selected in the SelectList. Here is the controller code that populates the list:

var statuses  = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);

Here is the View code:

<div class="display-label">
   Order Status</div>
<div class="editor-field">
   @Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
   @Html.ValidationMessageFor(model => model.StatusID)
</div>

I walk through it and even in the view it has the correct SelectedValue however the DDL always shows the first item in the list regardless of the selected value. Can anyone point out what I am doing wrong to get the DDL to default to the SelectValue?

Broder answered 6/4, 2012 at 4:5 Comment(4)
please refer the below link. #5189063Bushweller
alok_dida, I looked over that, it looks very similar except that the value selected in constructing the SelectList uses the entire object vs. the ID.ToString() like I am doing. However I changed my code to do the same and it did not resolve the problem. Is there some difference between the two that I am missing that will fix my problem?Broder
I added a detailed example of how it could be done.Pawsner
this can solve the problem of dd #11043160 Thanks.Steward
C
53

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)
Caespitose answered 6/4, 2012 at 6:19 Comment(5)
Excellent answer, thank you for both explaining the problem and giving an example of how to fix it. Thank you for the help.Broder
I dont actually understand where the StatusID binds? Isn't the fourth value of SelectList the selected value? You didn't actually tell the selectlist about that anywhere? Does it just know or am I going nuts? I cant get this to work to preselect many dropdowns :(Premolar
@ppumkin, no, when you use a view model and strongly typed helper you do not need the fourth argument of the SelectList constructor. That's what the x => x.StatusID does. By the way as you can see from my example I didn't even use the SelectList constructor because my view model property is IEnumerable<SelectListItem> and could directly be bound to the DropDownListFor.Caespitose
I never knew that. Thanks once again. I got it all working now :) So happy :)Premolar
Pre-populating the model solved me, well over an hour googling though!Moltke
F
4

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; }
}
Facing answered 2/11, 2017 at 17:13 Comment(2)
This one worked for me, but I refactor the property to a string.Wayside
Is any way to set it integer value in selection value.Cully
P
3

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.

Pawsner answered 6/4, 2012 at 13:23 Comment(0)
A
0

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.

Aciniform answered 6/10, 2018 at 1:58 Comment(0)
B
0

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.

Beanstalk answered 23/1, 2019 at 10:24 Comment(0)
O
0

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;
}
Oballa answered 2/8, 2019 at 10:30 Comment(0)
B
-3

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)
Bushweller answered 6/4, 2012 at 6:30 Comment(4)
I hope you just copied and pasted this code from some sample code. This could easily been done in a for loop. Sorry to be the code nazi, but honestly we should stop spreading bad code even when not using production code. Unless you're in intro to programming that's a whole different level.Cromwell
Guys, this was just an example. User can create a list in anyway. The way I created a list, which doesn't make any sense for him because he will have his own collection. The line which matters from him is last 2 lines of codes from C# and 2 lines of code from HTML. Please don't downvote the code without logic. You can also edit the post. You can downvote the answer if it's incorrect. What's the wrong thing in this code?Bushweller
@ppumkin - if your eyes are burning then edit the code. What's wrong in the code?Bushweller
@Cromwell - i didnt copy it from the Sample code. I just started writing code here and did copy paste. If you thing it's a bad code then edit it or drop a note to me but why did you give down vote? There is no reason for downvote.Bushweller

© 2022 - 2024 — McMap. All rights reserved.