2012-12-19 8 views
10

Hier ist der relevante Code. Wohlgemerkt, ich habe dies in Notepad ++ getan, anstatt meinen Code für mein Projekt bei der Arbeit zu kopieren. Wenn ich einen Klassennamen falsch geschrieben habe, gehe davon aus, dass es in meinem Code nicht falsch geschrieben ist. Keine KompilierungsfehlerRichtiger Weg DropDownListFor mit einer Liste primitiver Typen zu verwenden?

Modell:

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

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

Controller:

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

Ansicht (Razor):

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

Dies wird "Arbeit", aber keine Werte fest auf einem der gerendert option Elemente in der 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> 

Ich kenne die SelectList constructor, die die value und text in den option Elementen zu machen, zu verwenden, in den Eigenschaftsnamen nehmen, aber es nützt nichts, (dass ich sehen kann), wenn eine Sammlung primitiver mit Typ wie ein int.

Frage:

Ich weiß, ich kann IList<int> zu IList<SelectListItem>, meiner Meinung nach Modell ändern und SelectListItem Objekte erstellen, um jeden int darstellen, aber das scheint ein bisschen lächerlich (wie ich der Konstruktor sollte nicht denken, die Werte leer lassen und sollte standardmäßig den Text verwenden). Fehle ich etwas Offensichtliches hier, oder werde ich mich hier von primitiven Typen entfernen müssen?

Antwort

0

Ich löste dieses Problem, Erweiterungsmethoden verwenden, so dass Sie diese in Ihren Ansichten schreiben: Sie müssen möglicherweise

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

Für eine int Sammlung n => n.ToString() als Ihren Namen Wähler verwenden.

Die Schönheit dieses Ansatzes ist, dass Sie es für jede Art von aufzählbar verwenden können. In Ihrem Beispiel (mit einer Liste von Ganzzahlen) geben Sie einfach lambdas an, die das Element selbst zurückgeben, wodurch der Text und der Wert in der Liste der gerenderten Optionen auf denselben Wert gesetzt werden.

Wenn Sie vermeiden möchten, den Namespace der Erweiterungsklasse in Ihrer Web.config zu importieren, deklarieren Sie eine schreibgeschützte Eigenschaft in Ihrem ViewModel, die die SelectList zurückgibt, und greifen Sie dann in Ihrer Ansicht darauf zu.

Der Web.config-Teil würde in etwa so aussehen (beachten Sie, dass Sie eine Zeile für die Assembly und eine für den Namespace erstellen müssen). Beachten Sie außerdem, dass Ihr Views-Ordner eine separate Web.config enthält, die die Definitionen in Ihrem Stammweb.config überschreiben oder erweitern kann.

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

Dies ist die Implementierung für die Erweiterungsmethoden:

/// <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

Ich mag es. Werde es morgen bei der Arbeit benutzen! Code sieht echt aus, als Antwort, danke !! – Gromer

Verwandte Themen