John S
John S

Reputation: 8331

ASP.Net MVC view model for dropdownlist?

I am trying to work with a generated Month dropdownlist in MVC. My viewmodel is:

public class MyViewModel{

   public MyViewModel()
   {
      var monthNames = DateTimeFormatInfo.CurrentInfo.MonthNames.Take(12).ToList();
Months = new SelectList(monthNames.Select(m=> new{Id=monthNames.IndexOf(m)+1, Name=m}).ToList(),"Id","Name");
   }

   public IEnumerable<SelectListItem> Months{ get; set; }

   public string Month{ get; set; }

}

My View is:

@Html.DropDownListFor(model=>model.Month, new SelectList(Model.Months))

The problem is that the Months property always returns a null value so the page errors when trying to render the DDL.

Seems pretty simple. What am I missing?

Upvotes: 0

Views: 743

Answers (2)

Brad Christie
Brad Christie

Reputation: 101604

As another possible solution using templates:

// in your model, decorate it to use the template
[UIHint("MonthName")]
public String Month { get; set; }

Then in ~/Views/Shared/EditorTemplates/MonthName.cshtml:

@model String
@Html.DropDown(
  String.Empty,
  @Model,
  new SelectList(
    System.Globalization.DateTimeFormatInfo.CurrentInfo.MonthNames
      .Where(x => !String.IsNullOrEmpty(x))
      .Select((x,y) => new { Text = x, Value = y + 1 }),
    "Value",
    "Text"
  )
)

And finally, in your view:

@Html.EditorFor(x => x.Month)

though this is really only worth while on fixed-lists (like months), and not for things that may be dynamic based on the view being displayed.

Upvotes: 2

Chris Pratt
Chris Pratt

Reputation: 239250

You're missing the part where you actually set the Months property to something other than null.

You should just define a custom getter on the property so it always returns an enumerable:

public IEnumerable<SelectListItem> Months
{
    List<string> monthNames = DateTimeFormatInfo.CurrentInfo.MonthNames.Take(12).ToList();
    foreach (var month in monthNames)
    {
        yield return new SelectListItem
        {
            Value = monthNames.IndexOf(month) + 1,
            Text = month
        };
    }
}

Upvotes: 2

Related Questions