15

ASP.NET MVC Html ヘルパー拡張メソッドの中に拡張メソッドがあることは知っていListBoxForますが、リスト ボックスよりもチェックボックス リストの方が使いやすいとずっと思っていました。

CheckBoxList古き良き WebForms には非常に便利なコントロールがありましたが、明らかにそれは今ではありません。

問題は、ASP.NET MVC でチェック ボックス リストを作成する方法がないのはなぜですか? チェック ボックス リストを作成し、同様の動作をする独自の拡張メソッドを作成するにはどうすればよいListBoxForですか?

4

4 に答える 4

33

これは、ビューデータ モデルで選択した項目を配列として処理する、CheckBoxListFor の厳密に型指定された HtmlHelper です。チェックボックス リストに非表示の「false」フィールドが必要ないため、Html.CheckBox または Html.CheckBoxFor メソッドをラッパーしないことにしました。

これを改善して再投稿してください:-)

//View

<%: Html.CheckBoxListFor(model => model.FreightTypeIds, FreightTypeMultiSelectList)  %>

//Controller

    public ActionResult SomeAction(int[] FreightTypeIds)
    {
       //...

       return View();
    }


//Extension
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IEnumerable<TProperty>>> expression, MultiSelectList allOptions, object htmlAttributes = null)
{
    ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, IEnumerable<TProperty>>(expression, htmlHelper.ViewData);

    // Derive property name for checkbox name
    string propertyName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(modelMetadata.PropertyName);

    // Get currently select values from the ViewData model
    IEnumerable<TProperty> list = expression.Compile().Invoke(htmlHelper.ViewData.Model);

    // Convert selected value list to a List<string> for easy manipulation
    IList<string> selectedValues = new List<string>();

    if (list != null)
    {
        selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); });
    }

    // Create div
    TagBuilder divTag = new TagBuilder("div");
    divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);

    // Add checkboxes
    foreach (SelectListItem item in allOptions)
    {
        divTag.InnerHtml += string.Format(
                                          "<div><input type=\"checkbox\" name=\"{0}\" id=\"{1}_{2}\" " +
                                          "value=\"{2}\" {3} /><label for=\"{1}_{2}\">{4}</label></div>",
                                          propertyName,
                                          TagBuilder.CreateSanitizedId(propertyName),
                                          item.Value,
                                          selectedValues.Contains(item.Value) ? "checked=\"checked\"" : string.Empty,
                                          item.Text);
    }

     return MvcHtmlString.Create(divTag.ToString());
}
于 2010-10-30T04:43:29.417 に答える
2

私はまだ実験中ですが、これはデフォルトのバインダーとうまくいくようで、投稿後もユーザーの選択を保持します.隠しフィールド、本当に?? ..これはhtml5で飛ぶでしょうか?これはクレイジーに感じますが、ModelState.IsValid が false であるという理由だけで、ドロップダウン リストとチェックボックス リストのデータベースにアクセスするよりも、これを実行したいと思います。

        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, List<SelectListItem> list, string ModelCollectionName)
    {
        var sb = new StringBuilder();

        if (list != null)
        {
            int i = 0;

            foreach (var l in list)
            {
                string collectionNameIndex = String.Format("{0}[{1}]", ModelCollectionName, i);

                var hiddenName = new TagBuilder("input");
                hiddenName.Attributes.Add(new KeyValuePair<string, string>("type", "hidden"));
                hiddenName.Attributes.Add(new KeyValuePair<string, string>("name", String.Format("{0}.{1}", collectionNameIndex, "Text")));
                hiddenName.Attributes.Add(new KeyValuePair<string, string>("value", l.Text));

                var hiddenValue = new TagBuilder("input");
                hiddenValue.Attributes.Add(new KeyValuePair<string, string>("type", "hidden"));
                hiddenValue.Attributes.Add(new KeyValuePair<string, string>("name", String.Format("{0}.{1}", collectionNameIndex, "Value")));
                hiddenValue.Attributes.Add(new KeyValuePair<string, string>("value", l.Value));

                var checkBoxTag = htmlHelper.CheckBox(String.Format("{0}.{1}", collectionNameIndex, "Selected"), l.Selected);

                var labelTag = new TagBuilder("label");
                labelTag.Attributes.Add(new KeyValuePair<string, string>("for", String.Format("{0}.{1}", collectionNameIndex, "Name")));
                labelTag.SetInnerText(l.Text);

                sb.Append(hiddenName);
                sb.Append(hiddenValue);
                sb.Append(checkBoxTag);
                sb.Append(labelTag);
                sb.Append("<br/>");

                i++;
            }
        }

        return MvcHtmlString.Create(sb.ToString());
    }
于 2011-04-14T21:20:23.240 に答える
1

Microsoft の従業員はおそらく、そのようなヘルパー メソッドが存在しない理由を答えることができる唯一の人ですが、試してみることができます。

モデル:

public class MyViewModel
{
    public bool[] Values { get; set; }
}

コントローラ:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel 
        { 
            Values = new[] { true, false, true, false }
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

意見:

<% using (Html.BeginForm()) { %>
    <%: Html.EditorFor(x => x.Values) %>
    <input type="submit" value="OK" />
<% } %>

ご覧EditorForのとおり、必要なものはすべて処理されます。

于 2010-10-08T13:48:45.227 に答える
0

Jeremiah Clark によるCheckBoxList Helper for MVC の記事に興味があるかもしれません(残念ながら 2008 年 11 月の日付で、MVC 1 に関するものです)。

于 2010-10-08T11:14:40.350 に答える