在MVC的專案中,使用Razor語法產生ListBoxFor,提供使用者多選列表內資料
如何正確初始化空白的SelectList。
今天在開發MVC專案的時候,手邊有一個需求
需要產生兩個ListBox,一邊是從DB裡面帶出資料,一邊是讓使用者透過四個功能鍵選取,
紀錄一下如何使用Razor產生兩個ListBox
首先準備ViewMode
public class Condition
{
/// <summary>
/// 左邊實際選取的值
/// </summary>
public List<String> LEFT_DEPTID_List { get; set; }
/// <summary>
/// 右邊選取的值
/// </summary>
public List<String> RIGHT_DEPTID_List { get; set; }
}
public class ViewData
{
public Condition condition{get;set;}
/// <summary>
/// 左邊列表的內容資料(資料來源)
/// </summary>
public SelectList LEFT_DEPTID_SelectList { get; set; }
/// <summary>
/// 右邊列表的內容資料(資料來源)
/// </summary>
public SelectList RIGHT_DEPTID_SelectList { get; set; }
}
在第一次產生頁面的時候,我需要產生資料來源 ,
這邊要特別注意的是 空白SelectList的正確宣告方式 new SelectList( Enumerable.Empty<SelectListItem>());
public ActionResult DemoEdit()
{
ViewModel viewModel = new ViewModel();
//初始化左邊的資料列表
viewModel.LEFT_DEPTID_SelectList = 左邊要顯示的資料來源(Type:SelectList);
//右邊要帶入空白,因為使用者還沒選擇,要注意這邊是空白SelectList的正確宣告方式
viewModel.RIGHT_DEPTID_SelectList = new SelectList( Enumerable.Empty<SelectListItem>());
viewModel.condition = new Condition();
viewModel.condition.LEFT_DEPTID_List = new List<string>(); // 單位左邊已經選取的值,NULL,使用者還沒選
viewModel.condition.RIGHT_DEPTID_List = new List<string>(); // 單位右邊已經選取的值,NULL,使用者還沒選
return View(viewModel);
}
再來就是View的部分,使用Razor語法產生
<div class="form-group">
<label class="control-label col-md-2" for="selDEPID_OLD" style="display:inline;">單位代號:</label>
<div class="col-md-8">
<div style="display:inline-block;vertical-align:top;">
@Html.ListBoxFor(c => c.condition.LEFT_DEPTID_List, Model.LEFT_DEPTID_SelectList, new { @class = "form-control ", id = "selDEPID_OLD",disabled="disabled", style = "width:220px;height:160px;display:inline;margin-right:10px;" })
</div>
<div style="width:30px;height:160px;display:inline-block;vertical-align:top;">
<span style="cursor:pointer">
<input type="button" disabled class="btn" style="background-image:url('/Content/Images/arrow_double_right.jpg');width:25px;height:25px;" id="arrow_double_right" />
</span>
<br><br>
<span style="cursor:pointer">
<input type="button" disabled class="btn" style="background-image:url('/Content/Images/arrow_right.jpg');width:25px;height:25px;" id="arrow_right" />
</span>
<br><br>
<span style="cursor:pointer">
<input type="button" disabled class="btn" style="background-image:url('/Content/Images/arrow_left.jpg');width:25px;height:25px;" id="arrow_left" />
</span>
<br><br>
<span style="cursor:pointer">
<input type="button" disabled class="btn" style="background-image:url('/Content/Images/arrow_double_left.jpg');width:25px;height:25px;" id="arrow_double_left" />
</span>
</div>
<div style="display:inline-block;vertical-align:top;">
@Html.ListBoxFor(c => c.condition.RIGHT_DEPTID_List, Model.RIGHT_DEPTID_SelectList, new { @class = "form-control ", disabled = "disabled", id = "selDEPTID_CHOICE", style = "width:220px;height:160px;display:inline;margin-right:10px;" })
</div>
</div>
</div>
使用Razor產生的時候,注意
@Html.ListBoxFor(c => c.condition.LEFT_DEPTID_List, Model.LEFT_DEPTID_SelectList,....)
第一個參數是使用者選取的值(List<String>)=>POST到後端的時候就是POST這個資料。
第二個參數是畫面上要顯示的值
[HttpPost]
public ActionResult DemoEdit(ViewModel viewModel)
{
//這邊就可以看到viewModel.condition裡面兩個List<String>的資料
// LEFT_DEPTID_List,RIGHT_DEPTID_List
return View();
}
最後附上Javascript控制動態多選物件的語法
//單位 多選(=>)
function arrow_right_Click() {
var _selectArray = $('#selDEPID_OLD :selected');
if (_selectArray.length > 0) {
$.each(_selectArray, function (inedex, item) {
$('#selDEPTID_CHOICE').append(item);
});
}
}
//單位 多選(<=)
function arrow_left_Click() {
var _selectArray = $('#selDEPTID_CHOICE :selected');
if (_selectArray.length > 0) {
$.each(_selectArray, function (inedex, item) {
$('#selDEPID_OLD').append(item);
});
}
}
//單位 全選 全選(=>>)
function arrow_double_right_Click() {
var _selectArray = $('#selDEPID_OLD option');
if (_selectArray.length > 0) {
$.each(_selectArray, function (inedex, item) {
$('#selDEPTID_CHOICE').append(item);
});
}
}
//單位 全選 (<<=)
function arrow_double_left_Click() {
var _selectArray = $('#selDEPTID_CHOICE option');
if (_selectArray.length > 0) {
$.each(_selectArray, function (inedex, item) {
$('#selDEPID_OLD').append(item);
});
}
}
結論:
1.選取的值會用型態List<String>的方式POST到後端
2.顯示的值用SelectList給值,其實行為模式跟@Razor.DropDownListFor是很類似的
2017/08/03 補充:
測試的時候發現一個問題,已經將左邊的資料選到右邊的ListBox,但是POST到後端的時候,
ModelBinding的值不如預期,看一下下面這張圖
可以發現右邊的ListBix,001 是被selected的,
但是第二個option是沒有被選取,
真正透過Model Binding Post到後段的資料,是有被選取的值才會被POST到後端,
所以如果以目前我的需求(右邊ListBox的值都要儲存)
可以透過JS在存檔前將右邊ListBox的option都設為selected
$($('#selDEPTID_CHOICE option')).prop('selected',true);
這樣就可以正確地將所有右邊ListBox內的值都Post到後端,
當然如果沒有特殊需求,可以沿用現有機制,POST選取的值到後端即可!