2014-07-24 24 views
0

我想知道是否有方法在模型中從一個來源的客戶端創建多個DropDownLists。ASP.NET MVC 5從客戶端的單一來源創建多個DropDownLists

背景是我需要創建一個包含約30 DropDownLists視圖。 DropDownLists彼此相同,每個包含大約400個條目。我的模型包含一個

List<SelectListItem> StandardProductTypes 

保存每個DropDownList的所有條目。

這裏是在我當前視圖:

@for (int i = 0; i < Model.Mappings.Count; i++) 
{ 
    @Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey, 
         new SelectList(Model.StandardProductTypes, "Value", "Text", Model.Mappings[i].SelectedStandardProductTypeKey)) 
} 

正如你所看到的,這是從服務器返回的30×400 = 12000個條目,頁面加載相當緩慢。

真正需要的只有400個條目被傳輸,它們在瀏覽器的客戶端被複制30次。有沒有辦法實現這一點?任何提及閱讀材料或教程都會很好。

在此先感謝。

Nay

回答

0

好的,首先你不需要爲每個DropDownList創建一個新的SelectList作爲源。 DropDownListFor方法只需要一個IEnumerable<SelectListItem>作爲源,您已經擁有它(並且所選值由其通常的屬性值確定,所以您無需爲所選值明確傳遞此值。)

即給出「StandardProductTypes」已經IEnumberable<SelectListItem>你可以從

@Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey, 
         new SelectList(Model.StandardProductTypes, "Value", "Text", Model.Mappings[i].SelectedStandardProductTypeKey)) 

@Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey, 
         Model.StandardProductTypes) 

此外,我一般不會把東西像簡化DropDownListFor在模型中,因爲你不需要在回發後將它傳回。將它放在Viewbag中很好。

然而,這只是一個很好的做法,除此之外,因爲這裏的HTML仍然會包含所有下拉菜單的所有選項。爲了解決你的問題,你想回到它只有一次,然後使用一些客戶端的jQuery/javascript來複制它

EG:

使用

@Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey, new List<SelectListItem>()) 
@Html.Hidden(String.Format("Mappings[{0}].SelectedStandardProductTypeKey_Initial",i), Model.Mappings[i].SelectedStandardProductTypeKey) 

到位下拉的(所以你具有正確的初始值)

然後,在端部的位腳本的填補dropdownlists:

<script> 
var ddlVals= new Array(); 
@foreach(var item in Model.StandardProductTypes) // get all the select list items into a javascript array 
{ 
    @Html.Raw(String.Format("ddlVals.push(['{0}','{1}']);", item.Key, item.Value)) 
} 

$('input[type="select"][name$="SelectedStandardProductTypeKey"]').each(function() 
{ 
    var initValue $("name='" + $(this).attr("name") + "_Initial'").val(); 
    foreach(var item in ddlVals) 
    { 
    var html = '<option value="' + item[0] + '"' 
    if (item[0] == initValue){ html = html + ' selected="selected"'} 
    html = html + '>' + item[1] + '</option>'; 
    $(this).append(html); 
    } 
} 

</script> 

編輯

可能會更快使用Edi G's answer

的想法,但你仍然需要選擇正確的初始值。

所以,保持着隱藏字段和下拉菜單之上,但不是以前的劇本怎麼樣:

<!-- a template dropdownlist - hidden from view --> 
@Html.DropdownList("ddlTemplate", Model.StandardProductTypes, new {id = "ddlTemplate", style="display:none;"}) 
<script> 
$('input[type="select"][name$="SelectedStandardProductTypeKey"]').each(function() 
    { 
     $('#ddlTemplate option').clone().appendTo($(this)); 
     var initValue $("name='" + $(this).attr("name") + "_Initial'").val(); 
     $(this).val(initValue); 
    } 
</script> 

EDIT 2

如果仍然發現的頁面不響應時,JavaScript是在上面的編輯中嘗試腳本後填充下拉列表,然後我有另一種可能的解決方案。

您基本上需要將每個下拉列表中的源代碼填充爲新的List<SelectListItem> - 每個下拉列表僅包含一個選定的選項。

填充值的數組(根據原始腳本),但不是立即填充所有下拉列表中的某些javascript,它會在第一次放下下拉列表時填充數組中剩餘的值。

這樣你只加載一次400個項目的完整列表,而客戶端JavaScript只需要在單擊下拉菜單時執行工作,而不是在頁面加載時的所有30個下拉菜單。

+0

謝謝@James S.工作正常。但是,我收到'無反應的腳本'警告。當我點擊'繼續'時,它成功完成。代碼中是否有任何內容可以讓此警告框不顯示?另外,關於你寫的內容:「選擇的值由它通常使用的屬性值決定,所以你不需要爲顯示的值明確地傳遞它」。我試過只是爲了好奇,但在我的實例中不起作用,即如果我沒有明確指定選定的值,則下拉列表被設置爲第一項。 – Nay

+0

@Nay - 請參閱編輯我的答案,這可能會更快!此外,我通常使用'List '作爲我的下拉列表的源而不是'SelectList',並且只要其中一個SelectListItems具有與選中的屬性值匹配的值。 –

+0

謝謝@詹姆斯S.彈出仍然顯示,但我認爲我在一個屏幕上顯示太多。嘗試分頁,它工作正常。謝謝你的幫助。 – Nay

1

如何複製jQuery?

$('#myDropDownlist1 option').clone().appendTo('#myDropDownlist2'); 
+0

謝謝@Edi G.它幫助我。 – Nay