I would probably adapt the view model a little bit:
public class MyViewModel
{
public IEnumerable<ItemViewModel> Items { get; set; }
}
public class ItemViewModel
{
public int SelectedFilterId { get; set; }
public IEnumerable<SelectListItem> FilterListItems { get; set; }
public int SelectedId { get; set; }
public IEnumerable<SelectListItem> SelectionListItems { get; set; }
}
现在,我们的主要观点模式是,每个项目分别列出两个互换清单,用于过滤和甄选。 然后,我们有两个概念要在这里讨论:
- editing a variable length list
- cascading dropdown lists
The first point has been addressed by Steve Sanderson in this great post.
请谈第二点。 因此,我们将有4项行动:
- GET Index => called when the page is initially loaded. It will query our DAL and fetch domain models that will be mapped to MyViewModel which we need to pass to the corresponding view
- POST Index => called when the form is submitted in order to process the user input
- GET Filter => passed a filter id and returning a JSON object containing a list of key/value pairs corresponding to the respective items of the SelectionListItems drop down list.
- GET BlankEditorRow => returns a partial view representing a single group of drop down lists (see Steve Sanderson s blog post)
因此,请将此付诸行动:
public ActionResult Index()
{
var filters = ... fetch from repo and map to view model
var selectionItems = ... fetch from repo and map to view model
var model = new MyViewModel
{
// TOOO: fetch from repo and map to view model
Items = new[]
{
new ItemViewModel
{
SelectedFilterId = 1,
FilterListItems = filters,
SelectionListItems = selectionItems
},
new ItemViewModel
{
SelectedFilterId = 3,
FilterListItems = filters,
SelectionListItems = selectionItems
},
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// TODO: process the selected values here
...
}
public ActionResult Filter(int filterId)
{
return Json(_repository.GetSelectionItems(filterId));
}
public ActionResult BlankEditorRow()
{
var filters = ... fetch from repo and map to view model
var selectionItems = ... fetch from repo and map to view model
var model = new ItemViewModel
{
SelectedFilterId = 1,
FilterListItems = filters,
SelectionListItems = selectionItems
};
return PartialView("~/views/home/editortemplates/itemviewmodel.cshtml", model);
}
下一步是界定<代码>~/Views/Home/Index.cshtml>。 观点:
@model MyViewModel
@using (Html.BeginForm())
{
<ul id="editorRows">
@Html.EditorFor(x => x.Items)
</ul>
<button type="submit">OK</button>
}
@Html.ActionLink("Add another group of ddls", "BlankEditorRow", null, new { id = "addItem" })
以及相应的编辑模板(~/Views/Home/EditorTemplates/ItemViewModel.cshtml
):
@model ItemViewModel
<li>
<div>
@using (Html.BeginCollectionItem("items"))
{
@Html.DropDownListFor(
x => x.SelectedFilterId,
new SelectList(Model.FilterListItems, "Value", "Text", Model.SelectedFilterId),
new { @class = "filter", data_filter_url = Url.Action("Filter") }
)
@Html.DropDownListFor(
x => x.SelectedId,
new SelectList(Model.SelectionListItems, "Value", "Text", Model.SelectedId),
new { @class = "selection" }
)
}
</div>
</li>
The last step is to wire up the cascading drop down list and the possibility to add groups dynamically using javascript. So in a separate js file:
var filterChange = function () {
$( ul .filter ).unbind( change ).bind( change , function () {
$.ajax({
url: $(this).data( filter-url ),
type: GET ,
cache: false,
data: { filterId: $(this).val() },
context: { selectionDdl: $(this).closest( li ).find( .selection ) },
success: function (items) {
var selectionDdl = this.selectionDdl;
selectionDdl.empty();
$.each(items, function (index, item) {
selectionDdl.append($( <option/> , {
value: item.ID,
text: item.Name
}));
});
}
});
});
};
$(function () {
filterChange();
$( #addItem ).click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$( #editorRows ).append(html);
filterChange();
}
});
return false;
});
});