2013-07-17 11 views
10

mam następujący wiersz kodu:DropDownListFor nie przestrzegając wybranej właściwości z selectList

@Html.DropDownListFor(x => x.TimeOption, new SelectList(Model.TimeOptions, "Value", "Name", (int)Model.TimeOption)) 

Spadek w dół jest prawidłowo zbudowany i wybraniu rzeczywiście prawidłowe, ale MVC nie zwróci listy rozwijanej z odpowiedniej pozycji wybrany. Znacznik nie wyprowadza wybranego atrybutu dla opcji.

Wyjście jest wyświetlany jako:

<option value="0">Past Day</option> 
<option value="1">Past Week</option> 
<option value="2">Past Month</option> 
<option value="3">Past Year</option> 
<option value="4">Start of Time</option> 

Jednak jeśli spojrzeć na załączonym zrzucie ekranu widać, że jest prawidłowo wybrany:

Watch list

Wpływa to tylko dostać, nie post. Pomysły?

+0

czy można ująć ją bardziej wyraźnie, tak jak to jest w przypadku problemu? –

+0

Kiedy masz na myśli GET, wartość opcji zostanie zresetowana po odświeżeniu? –

+0

@RameezAhmedSayad, kiedy ładuje się strona (IE GET), domyślna wartość nie jest renderowana jako "selected =" selected "", ale w przypadku POST jest. Podczas GET ustawiona jest inna niż domyślna wartość (2). – Sam

Odpowiedz

22

To często skraca ludzi - podobno mapa drogowa dla MVC 5 zawiera bardziej intuicyjną pomoc dla DropDownList.

Kiedy zrobić:

@Html.DropDownListFor(x => x.TimeOption ...) 

... pomocnika HTML zrobi wszystko co w jego mocy nie użyć wartości ustawionej na Selected = true w swoim SelectList. Będzie:

  • Spróbuj dostać od ModelState - który nie otrzyma na żądanie GET
  • postarać się go z ViewData - co to będzie dostać, bo masz TimeOption nieruchomości na twój model.

Tylko jeśli obie te próby się nie powiedzie, ulegnie ona i użyje tego, o co go poprosiłeś.

W twoim przypadku użyje aktualnej wartości TimeOption w twoim modelu jako wybranej wartości. Co powinno być w porządku, ponieważ o to prosiliście w swoim SelectList ((int)Model.TimeOption), prawda?

Nieprawidłowy. Ponieważ będzie to , a nie rzucić swoją własność (enum?) Na int tak jak ty. Przekształci go w ciąg znaków. W przypadku modelu enum, który podaje nazwę wyliczenia - np. PastMonth. Jeśli TimeOption jest twoją niestandardową klasą, będzie to wynik ToString().

Następnie, jeśli nie znajdzie tego ciągu jako jednej z twoich wartości <select> (ponieważ są to liczby całkowite), decyduje się nie robić niczego wybranego.

W skrócie: SelectListItem.Selected nie ma wpływu na pomocnika. Jeśli twoje wywołanie pomocnicze określa nazwę (dosłownie lub przez wyrażenie lambda), helper użyje cokolwiek w tej nazwie z ModelState lub ViewData i przekształci ją w ciąg znaków.

W większości przypadków dzieje się to przy wyliczeniach. Najprostszym sposobem obejścia tego problemu jest użycie nazwy wyliczenia, a nie reprezentacji int, jako wartości dla SelectListItem.

+1

Wydaje się, że to niedopatrzenie lub dziwna decyzja projektowa. Przypisałem całkowitą wartość wyliczenia do ViewData i działa. Dzięki za pomoc. – Sam

+0

Dzięki, zaoszczędziło mi to dużo czasu. Zdecydowanie powinni to zrobić, to całkiem getto, do zrobienia ... ViewBag.RentFrequencies = Enums.RentFrequency.Monthly.ToDictionary(). Wybierz (x => nowy SelectListItem { Tekst = x.Value, Wartość = x .Key.ToString(), Selected = (x.Key == (int) tenant.RentFrequency) }). ToList(); ViewBag.RentFrequency = (int) tenant.RentFrequency; – Justin

+0

W moim przypadku właściwość modelu użytą dla wybranej wartości to "Tytuł" (jak w zwrot grzecznościowy). Ta sama właściwość została ustawiona w ViewData dla tytułu strony. Bardzo irytujące. –

2

Masz już dobre wyjaśnienie powyżej, dlaczego jej nie działa, ale tylko dodać mój 2p

Generalnie wolę za pomocą przeliczalny z SelectListItems jako źródła dropdownitems, albo chociaż powinno działać. Lepiej jest zrobić to w ten sposób, ponieważ nie ma potrzeby określania, który element jest wybrany - pomocnik MVC wywnioskuje go z wartości tej, która jest zgodna z metodą TimeOption.ToString().

tj

@Html.DropDownListFor(x => x.TimeOption, ((IEnumerable<TimeOption>)Model.TimeOptions).ToList().ConvertAll(y => new SelectListItem(){Text = y.Name, Value = y.Value.ToString()}) 

NB - nie jestem pewien, jaki typ Model.TimeOptions jest tutaj - jeśli jej nie IEnumerable < TimeOption> następnie należy go wymienić. (jeśli jest to już lista, wtedy nie jest wymagana funkcja .ToList()).

Powiązane problemy