Проблема с DropDownListFor SelectedItem

Это меня полностью озадачило.

Вот мой взгляд:

@Html.DropDownListFor(model => model.ScoreDescription, 
                               Model.RatingOptions, 
                               "--", 
                               new { @id = clientId })

И модель:

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;
    }
}

Как следует из комментариев, я не могу получить выбранное значение.

Это как-то связано с тем, что я использую decimal, допускающий значение NULL? После этого цикла options верен в том смысле, что у него ровно 1 элемент с select, равным true, поэтому кажется, что я поступаю правильно.

Теперь, если я использую другую SelectList перегрузку:

var selectedValue = Score.HasValue ? Score.Value.ToString("0") : string.Empty;
var selectList = new SelectList(options, "Value", "Text", selectedValue);

Оно работает. Почему? Сначала я подумал, что это может быть LINQ-трюк (например, отложенное выполнение), но я попытался заставить .ToList(), и разницы нет.

Это похоже на установку свойства Selected при создании SelectListItem не имеет никакого эффекта, и вы должны установить его в конце с помощью параметра SelectList ctor.

Может кто-нибудь пролить некоторый свет на это?


person RPM1984    schedule 05.05.2011    source источник


Ответы (1)


Если вы посмотрите на реализацию класса SelectList, он на самом деле никогда не использует тот факт, что вы передаете SelectListItem. Работает с IEnumerable. Таким образом, свойство Selected SelectListItem не используется. Лично я предпочитаю устанавливать значение selected в раскрывающемся списке, задав значение соответствующего свойства, к которому вы привязываете ddl.

Пример:

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");
    }
}

а затем в действии контроллера просто установите для свойства Score необходимое значение и в представлении используйте это свойство Score для привязки к:

@Html.DropDownListFor(
    model => model.Score, 
    Model.RatingOptions, 
    "--", 
    new { @id = clientId }
)
person Darin Dimitrov    schedule 05.05.2011
comment
Итак, в основном мое последнее предложение верное - свойство Selected для SelectListItem в этом сценарии бессмысленно. Ваше здоровье. - person RPM1984; 05.05.2011