53

有沒有辦法在ViewModel上預先填充具有數據屬性的SelectList?具有數據屬性的SelectListItem

我想做

@Html.DropdownListFor(m=> m.CityId, Model.Cities); 

因此產生類似的代碼:

<select id="City" class="location_city_input" name="City"> 
    <option data-geo-lat="-32.522779" data-geo-lng="-55.765835" data-geo-zoom="6" /> 
    <option data-geo-lat="-34.883611" data-geo-lng="-56.181944" data-geo-zoom="13" data-geo-name="Montevideo" data-child=".state1" value="1">Montevideo</option>    
    <option data-geo-lat="-34.816667" data-geo-lng="-55.95" data-geo-zoom="13" data-geo-name="Canelones, Ciudad de la Costa" data-child=".state41" value="41">Ciudad de la Costa</option> 
</select> 

回答

83

下面是簡單的解決方案。

並非所有東西都必須用.NET代碼中的擴展方法編寫。 MVC的優點之一是它可以讓你輕鬆訪問構建自己的HTML。

隨着MVC4你可以得到表達式樹中的元素的ID和名稱與助手HTML.NameForHTML.IdFor

<select name="@Html.NameFor(Function(model) model.CityId)" 
     id="@Html.IdFor(Function(model) model.CityId)" 
     class="location_city_input"> 
    @For Each city In Model.Cities 
     @<option value="@city.Value" 
       @(If(city.Value = Model.CityId, "selected", "")) 
       data-geo-lat="@city.Lat" 
       data-geo-lng="@city.Lng" 
       data-geo-zoom="@city.Zoom"> 
      @city.Text 
     </option> 
    Next 
</select> 

假設Model.Cities是暴露每個屬性的項目的集合。那麼你應該全部設置。

如果你想重用性,可考慮將其用於任何一個編輯器模板是城市

+2

有趣......我沒「知道約html.namefor等我給它一個嘗試 –

+1

很好的建議,添加真正的輕鬆靈活的HTML。 – ChandlerPelhams

+5

由於razor2你可以簡單的做'選擇=‘@ city.Value == Model.CityId’'並且它會生成正確的標記(或者是'selected =「selected」'或者什麼也不是) – Diego

9

你將不得不延長SelectListItem,然後再擴展DropDownListFor使用擴展SelectListItem。

看一看這個解決方案:

Adding html class tag under <option> in Html.DropDownList

+1

這個貌似正確的答案,但似乎有點難看的枚舉。我寧願寫自己選擇比擴展SelectListItem和DropDownListFor我認爲。我不確定。 –

+3

我不知道你爲什麼覺得這很醜,但對我來說似乎更合乎邏輯。每個SelectListItem代表最後一個html中的一個選項標籤,你需要做的是將自定義html屬性添加到選項標籤(SelectListItem)中,所以擴展SelectListItem只是有意義的。 – ataravati

+1

我認爲從mvc框架的角度來看它很醜。但解決方案正是如何處理。 –