Html.CheckBoxList が拡張機能であり、それが生成したマークアップであると想定しています。
表示内容に基づいて、次の 2 つの点を確認してください。
- モデル バインダーは、バインド先の文字列プロパティ h_dist_cd を持つ Header という名前のオブジェクトを探します。アクション メソッドは、Header がモデルの子オブジェクトではなくルート ビュー モデルであるように見えます。
- チェックボックスがオフになっている場合の処理方法がわかりません。通常のトリックは、同じ名前の非表示フィールドをレンダリングすることです。
また、「label for="..."」を使用して、テキストをクリックしてチェック/チェック解除し、アクセシビリティを確保できるようにします。
この問題に拡張機能を使用するとエラーが発生しやすいことがわかりました。代わりに、子ビュー モデルを検討することをお勧めします。MVC2 の EditorFor テンプレート システムにより適しています。
これが私たちのシステムの例です...
ビューモデルに、再利用可能な子モデルを埋め込みます...
[AtLeastOneRequired(ErrorMessage = "(required)")]
public MultiSelectModel Cofamilies { get; set; }
SelectListItem の標準リストで初期化できます...
MyViewModel(...)
{
List<SelectListItem> initialSelections = ...from controller or domain layer...;
Cofamilies = new MultiSelectModel(initialSelections);
...
MultiSelectModel 子モデル。Value... の setter オーバーライドに注意してください。
public class MultiSelectModel : ICountable
{
public MultiSelectModel(IEnumerable<SelectListItem> items)
{
Items = new List<SelectListItem>(items);
_value = new List<string>(Items.Count);
}
public int Count { get { return Items.Count(x => x.Selected); } }
public List<SelectListItem> Items { get; private set; }
private void _Select()
{
for (int i = 0; i < Items.Count; i++)
Items[i].Selected = Value[i] != "false";
}
public List<SelectListItem> SelectedItems
{
get { return Items.Where(x => x.Selected).ToList(); }
}
private void _SetSelectedValues(IEnumerable<string> values)
{
foreach (var item in Items)
{
var tmp = item;
item.Selected = values.Any(x => x == tmp.Value);
}
}
public List<string> SelectedValues
{
get { return SelectedItems.Select(x => x.Value).ToList(); }
set { _SetSelectedValues(value); }
}
public List<string> Value
{
get { return _value; }
set { _value = value; _Select(); }
}
private List<string> _value;
}
これで、エディター テンプレートを Views/Shared/MultiSelectModel.ascx... に配置できます。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<WebUI.Cofamilies.Models.Shared.MultiSelectModel>" %>
<div class="set">
<%=Html.LabelFor(model => model)%>
<ul>
<% for (int i = 0; i < Model.Items.Count; i++)
{
var item = Model.Items[i];
string name = ViewData.ModelMetadata.PropertyName + ".Value[" + i + "]";
string id = ViewData.ModelMetadata.PropertyName + "_Value[" + i + "]";
string selected = item.Selected ? "checked=\"checked\"" : "";
%>
<li>
<input type="checkbox" name="<%= name %>" id="<%= id %>" <%= selected %> value="true" />
<label for="<%= id %>"><%= item.Text %></label>
<input type="hidden" name="<%= name %>" value="false" />
</li>
<% } %>
</ul>
<%= Html.ValidationMessageFor(model => model) %>
このアプローチには 2 つの利点があります。
項目のリストを選択値とは別に扱う必要はありません。単一のプロパティに属性を設定できます (たとえば、AtLeastOneRequired はシステムのカスタム属性です)。
モデルとビュー (エディター テンプレート) を分離します。たとえば、チェックボックスの水平レイアウトと垂直レイアウトがあります。「複数選択」を、前後のボタンを備えた 2 つのリストボックス、複数選択リスト ボックスなどとしてレンダリングすることもできます。