ネストされたコレクションが含まれているため、ViewModel は非常に複雑です。デフォルトのモデル バインダーを使用して入力値をモデルにバインドする方法はないと思います。カスタム モデル バインダーを作成する必要があります。カスタム モデル バインダーを実装しようとしました。これが私の実装 ListDictionary モデル バインダーです。
カスタムモデルバインダー
public class ListDictionaryModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var resultList = new List<Dictionary<int, bool>>();
var forms = controllerContext.HttpContext.Request.Form;
var regex = new Regex(@"(true,)?false");
var result =
forms.AllKeys.Select(x => new {key = x, value = forms[x]}).Where(x => x.key.Contains("Columns")).ToList();
result.ForEach(x =>
{
var matches = regex.Matches(x.value);
var dictionary = new Dictionary<int, bool>();
for (var i = 0; i < matches.Count; i++)
{
var value = matches[i].ToString() == "true,false" ? true : false;
dictionary.Add(i, value);
}
resultList.Add(dictionary);
});
return resultList;
}
}
使用例
コントローラ:
public ActionResult Index()
{
//example data
var viewModel = new ViewModel
{
Columns = new List<Dictionary<int, bool>>
{
new Dictionary<int, bool> {{1, false}, {2, false}},
new Dictionary<int, bool> {{1, false}, {2, false}}
}
};
return View(viewModel);
}
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
//viewModel - contains values of user input
return View();
}
インデックス ビュー:
@model RepositoryTestProject.ViewModels.ViewModel
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>ViewModel</legend>
@Html.EditorFor(x => Model.Columns,"_ColumnEdit")
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
部分ビュー: (「/Views/Shared」に「EditorTemplates」フォルダーを作成し、部分テンプレートをフォルダーに配置する必要があります)
_ColumnEdit 部分ビュー:
@model List<Dictionary<int,bool>>
@for(int i =0; i < Model.Count();i++)
{
@Html.EditorFor(x=>Model[i],"_DictEdit")
}
_DictEdit 部分ビュー:
@model Dictionary<int, bool>
@for(int i =0; i < Model.Count();i++)
{
@Html.CheckBoxFor(x=>Model.ElementAt(i).Value)
}
global.asax にモデル バインダーを登録する必要があります
ModelBinders.Binders.Add(typeof(List<Dictionary<int,bool>>), new ListDictionaryModelBinder());
最後に、次のようにコントローラーで値を取得できます。
