23

I'm working on a MVC3 web application. I want a list of categories shown when editing a blo from whe applications managements system. In my viewmodel i've got the following property defined for a list of selectlistitems for categories.

/// <summary>
/// The List of categories
/// </summary>
[Display(Name = "Categorie")]
public IEnumerable<SelectListItem> Categories { get; set; }

The next step, my controller contains the following edit action where the list of selectlistitems is filled from the database.

public ActionResult Edit(Guid id)
{
    var blogToEdit = _blogService.First(x => x.Id.Equals(id));
    var listOfCategories = _categorieService.GetAll();
    var selectList = listOfCategories.Select(x =>new SelectListItem{Text = x.Name, Value = x.Id.ToString(), Selected = x.Id.Equals(blogToEdit.Category.Id)}).ToList();
    selectList.Insert(0, new SelectListItem{Text = Messages.SelectAnItem, Value = Messages.SelectAnItem});

    var viewModel = new BlogModel
                        {
                            BlogId = blogToEdit.Id,
                            Active = blogToEdit.Actief,
                            Content = blogToEdit.Text,
                            Title = blogToEdit.Titel,
                            Categories = selectList //at this point i see the expected item being selected
                            //Categories = new IEnumerable<SelectListItem>(listOfCategories, "Id", "Naam", blogToEdit.CategorieId)
                        };
    return View(viewModel);
}

When i set a breakpoint just before the view is being returned, i see that the selectlist is filled as i expected. So at this point everything seems to be okay. The viewmodel is filled entirely correct. Then in my view (i'm using Razor) i've got the following two rules which are supposed to render the selectlist for me.

@Html.LabelFor(m => m.Categories) @Html.DropDownListFor(model=>model.Categories, Model.Categories, Model.CategoryId)
@Html.ValidationMessageFor(m => m.Categories)

When I run the code and open the view to edit my blog, I can see all the correct data. Also the selectlist is rendered correctly, but the item i want to be selected lost it's selection. How can this be? Until the point the viewmodel is being returned with the view everything is okay. But when i view the webpage in the browser, the selectlist is there only with out the correct selection. What am I missing here? Or doing wrong?

Barney
  • 2,355
  • 3
  • 22
  • 37
Rob
  • 6,731
  • 12
  • 52
  • 90

2 Answers2

51
@Html.DropDownListFor(model=>model.Categories, Model.Categories, Model.CategoryId)

Here you are not properly using the helper method. The first argument must be a property on your view model which will contain the currently selected value. It should be a scalar property, not a collection.

So in your view model you need to add such property:

[Display(Name = "Categorie")]
public IEnumerable<SelectListItem> Categories { get; set; }
public string SelectedValue { get; set; }

And in your controller action:

var selectList = listOfCategories.Select(x => new SelectListItem {
    Text = x.Name, 
    Value = x.Id.ToString() 
}).ToList();

var viewModel = new BlogModel
{
    BlogId = blogToEdit.Id,
    Active = blogToEdit.Actief,
    Content = blogToEdit.Text,
    Title = blogToEdit.Titel,
    Categories = selectList,
    // this is what sets the selected value
    SelectedValue = blogToEdit.Category.Id 
};

And in your view simply:

@Html.DropDownListFor(x => x.SelectedValue, Model.Categories)
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Pretty sure you are right, however, the property should be named CategoryId, not SelectedValue (I know, a bit of a nitpick, +1 anyway :) ) – Chris Shaffer Jan 02 '11 at 17:52
  • Thanks for the quick and very clear answer! That worked great! – Rob Jan 02 '11 at 17:52
  • @Chris Shaffer, yes I agree that it would be better named `CategoryId` instead of `SelectedValue` as it better reflects its purpose. – Darin Dimitrov Jan 02 '11 at 17:53
  • @Chris Shaffer. Named the property CategoryId and changed the implementation a bit. As said before, works great. Thanks! – Rob Jan 02 '11 at 17:58
  • I got an error on categories.Select(x => new SelectListItem..).ToList(). In stead I had to use categories.ToList().Select(x => new SelectListItem..), because the first Linq query cannot be resolved to the database. Unless 1+ – Dev.Jaap Jun 20 '13 at 11:42
1

I'm pretty sure I've used the selected=true property of a select list item to good effect before. One problem I had was a conflicting value in ViewData.

nick
  • 1,477
  • 2
  • 20
  • 29