2012-12-19 11 views
10

Oto odpowiedni kod. Pamiętaj, zrobiłem to w Notepad ++ zamiast kopiować w moim kodzie do mojego projektu w pracy. Jeśli błędnie wpisałam w nim nazwę klasy, załóżmy, że nie jest błędnie wpisana w moim kodzie. Brak błędów kompilacji.Prawidłowy sposób korzystania z DropDownListFor z listą typów pierwotnych?

Model:

public class MyViewModel 
{ 
    public int SelectedSomething { get; set; } 

    public IList<int> Somethings { get; set; } 
} 

Kontroler:

public class MyController 
{ 
    public ActionResult Index() 
    { 
     var viewModel = new MyViewModel(); 
     viewModel.Somethings = Enumerable.Range(1, 12).ToList(); 
     return View(viewModel); 
    } 
} 

View (Razor):

@Html.DropDownListFor(x => x.SelectedSomething, new SelectList(Model.Somethings, Model.SelectedSomething), "Select an Option") 

To będzie "działać", ale nie będą ustawione wartości na wybrane renderowane elementy option w select:

<select> 
    <option value="">Select an Option</option> 
    <option>1</option> 
    <option>2</option> 
    <option>3</option> 
    <option>4</option> 
    <option>5</option> 
    <option>6</option> 
    <option>7</option> 
    <option>8</option> 
    <option>9</option> 
    <option>10</option> 
    <option>11</option> 
    <option>12</option> 
</select> 

wiem o SelectList constructor że bierze w nazwach własności używać do renderowania value i text w option elementów, ale jest bezużyteczna (że widzę) przy użyciu zbiór prymitywne wpisz jak int.

Pytanie:

wiem, że mogę zmienić mój widok modelu na IList<int> do IList<SelectListItem> i tworzyć SelectListItem obiektów do reprezentowania każdego int, ale to wydaje się nieco śmieszne (jak myślę, że konstruktor nie powinien pozostawiać wartości puste i powinien domyślnie używać tekstu). Czy brakuje tu czegoś oczywistego, czy też będę musiał odejść od używania tutaj typów pierwotnych?

Odpowiedz

0

I rozwiązać ten problem przy użyciu metody rozszerzenie, dzięki czemu można napisać to w widokach:

@Html.DropDownListFor(x => x.SelectedSomething, 
         Model.Somethings.ToSelectList(n => n, v => v), 
         "Select an Option") 

Dla int kolekcji może trzeba użyć n => n.ToString() jako selektor nazwa.

Piękno tego podejścia polega na tym, że można go używać do dowolnego przelicznika. W twoim przykładzie (z listą liczb całkowitych), po prostu podajemy lambdas, które zwracają sam element, co spowoduje, że tekst i wartość zostaną ustawione na tę samą wartość na wyświetlonej liście opcji.

Jeśli chcesz uniknąć importowania przestrzeni nazw klasy rozszerzeń w pliku Web.config, zadeklaruj właściwość tylko do odczytu w swoim ViewModelu, który zwraca SelectList, a następnie uzyskaj dostęp do tego widoku.

Część Web.config wyglądałaby tak (zwróć uwagę, że musisz utworzyć linię zarówno dla złożenia, jak i dla obszaru nazw). Zauważ również, że twój folder Widoki zawiera oddzielny plik Web.config, który może przesłonić lub rozszerzyć definicje w głównym pliku Web.config.

<system.web> 
    <compilation debug="true" targetFramework="4.0" batch="true"> 
     <assemblies> 
      <add assembly="My.Web.Stuff" /> 
     </assemblies> 
    </compilation> 
    <pages> 
     <namespaces> 
      <add namespace="My.Web.Stuff.Extensions" /> 
     </namespaces> 
    </pages> 
</system.web> 

Jest to realizacja dla metod rozszerzenie:

/// <summary> 
/// Extension methods on IEnumerable. 
/// </summary> 
public static class SelectListExtensions 
{ 
    /// <summary> 
    /// Converts the source sequence into an IEnumerable of SelectListItem 
    /// </summary> 
    /// <param name = "items">Source sequence</param> 
    /// <param name = "nameSelector">Lambda that specifies the name for the SelectList items</param> 
    /// <param name = "valueSelector">Lambda that specifies the value for the SelectList items</param> 
    /// <returns>IEnumerable of SelectListItem</returns> 
    public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector) 
    { 
     return items.ToSelectList(valueSelector, nameSelector, x => false); 
    } 

    /// <summary> 
    /// Converts the source sequence into an IEnumerable of SelectListItem 
    /// </summary> 
    /// <param name = "items">Source sequence</param> 
    /// <param name = "nameSelector">Lambda that specifies the name for the SelectList items</param> 
    /// <param name = "valueSelector">Lambda that specifies the value for the SelectList items</param> 
    /// <param name = "selectedItems">Those items that should be selected</param> 
    /// <returns>IEnumerable of SelectListItem</returns> 
    public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, IEnumerable<TValue> selectedItems) 
    { 
     return items.ToSelectList(valueSelector, nameSelector, x => selectedItems != null && selectedItems.Contains(valueSelector(x))); 
    } 

    /// <summary> 
    /// Converts the source sequence into an IEnumerable of SelectListItem 
    /// </summary> 
    /// <param name = "items">Source sequence</param> 
    /// <param name = "nameSelector">Lambda that specifies the name for the SelectList items</param> 
    /// <param name = "valueSelector">Lambda that specifies the value for the SelectList items</param> 
    /// <param name = "selectedValueSelector">Lambda that specifies whether the item should be selected</param> 
    /// <returns>IEnumerable of SelectListItem</returns> 
    public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, Func<TItem, bool> selectedValueSelector) 
    { 
     return from item in items 
       let value = valueSelector(item) 
       select new SelectListItem 
         { 
         Text = nameSelector(item), 
         Value = value.ToString(), 
         Selected = selectedValueSelector(item) 
         }; 
    } 
} 
+0

mi się podoba. Użyję go jutro w pracy! Kod wygląda legalnie, oznaczając jako odpowiedź, dzięki! – Gromer

Powiązane problemy