3

このコード:

Html.CheckBoxList(ViewData.TemplateInfo.HtmlFieldPrefix, myList)

このマークアップを生成します:

<ul><li><input name="Header.h_dist_cd" type="checkbox" value="BD" />
        <span>BD - Dist BD Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="SS" />
        <span>SS - Dist SS Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="DS" />
        <span>DS - Dist DS Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="SW" />
        <span>SW - Dist SW Name </span></li>
</ul>

複数の選択を確認できます。戻り文字列パラメーターHeader.h_dist_cdには、選択された最初の値のみが含まれます。他のチェック済みの値を取得するにはどうすればよいですか?

post メソッドのパラメーターは次のようになります。

public ActionResult Edit(Header header)
4

3 に答える 3

4

Html.CheckBoxList が拡張機能であり、それが生成したマークアップであると想定しています。

表示内容に基づいて、次の 2 つの点を確認してください。

  1. モデル バインダーは、バインド先の文字列プロパティ h_dist_cd を持つ Header という名前のオブジェクトを探します。アクション メソッドは、Header がモデルの子オブジェクトではなくルート ビュー モデルであるように見えます。
  2. チェックボックスがオフになっている場合の処理​​方法がわかりません。通常のトリックは、同じ名前の非表示フィールドをレンダリングすることです。

また、「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 つの利点があります。

  1. 項目のリストを選択値とは別に扱う必要はありません。単一のプロパティに属性を設定できます (たとえば、AtLeastOneRequired はシステムのカスタム属性です)。

  2. モデルとビュー (エディター テンプレート) を分離します。たとえば、チェックボックスの水平レイアウトと垂直レイアウトがあります。「複数選択」を、前後のボタンを備えた 2 つのリストボックス、複数選択リスト ボックスなどとしてレンダリングすることもできます。

于 2010-07-30T08:21:17.363 に答える
1

同じ名前のアイテムが複数ある場合、それらの値はコンマで区切られます

于 2010-07-30T09:05:03.470 に答える