This has totally puzzled me.
Here's my View:
@Html.DropDownListFor(model => model.ScoreDescription,
Model.RatingOptions,
"--",
new { @id = clientId })
And the model:
public decimal? Score { get; set; }
public SelectList RatingOptions
{
get
{
var options = new List<SelectListItem>();
for (var i = 1; i <= 5; i++)
{
options.Add(new SelectListItem
{
Selected = Score.HasValue && Score.Value == Convert.ToDecimal(i),
Text = ((decimal)i).ToRatingDescription(ScoreFactorType),
Value = i.ToString()
});
}
var selectList = new SelectList(options, "Value", "Text");
// At this point, "options" has an item with "Selected" to true.
// Also, the underlying "MultiSelectList" also has it.
// Yet selectList.SelectedValue is null. WTF?
return selectList;
}
}
As the comments suggest, i can't get the selected value to happen.
Is it something to do with the fact i'm using a nullable decimal
? After that loop, options
is correct in that it has exactly 1 item with select to true, so it seems i'm doing the right thing.
Now, if i use a different SelectList
overload:
var selectedValue = Score.HasValue ? Score.Value.ToString("0") : string.Empty;
var selectList = new SelectList(options, "Value", "Text", selectedValue);
It works. Why? At first i thought it might be a LINQ-trick (e.g deferred execution), but i tried forcing a .ToList()
and there is no difference.
It's like setting the Selected
property as you create the SelectListItem
has no effect, and you have you set it at the end using the SelectList
ctor parameter.
Can anyone shed some light on this?
If you look at the implementation of the SelectList class it never actually uses the fact that you are passing a SelectListItem
. It works with an IEnumerable
. So the Selected
property of a SelectListItem
is not used. Personally I prefer setting the selected value of a dropdown by setting the value of the corresponding property that you are binding the ddl to.
Example:
public int? Score { get; set; }
public SelectList RatingOptions
{
get
{
var options = Enumerable.Range(1, 5).Select(i => new SelectListItem
{
Text = ((decimal)i).ToRatingDescription(ScoreFactorType),
Value = ((decimal)i).ToString()
});
return new SelectList(options, "Value", "Text");
}
}
and then in the controller action simply set the Score
property to the necessary value and in the view use this Score property to bind to:
@Html.DropDownListFor(
model => model.Score,
Model.RatingOptions,
"--",
new { @id = clientId }
)