ASP.Net MVC 3 - CheckBoxList - 需要一些建议

时间:2011-07-14 14:39:37

标签: asp.net asp.net-mvc-3 razor

我是ASP.Net MVC(和razor)的新手,我有几个问题。

1)

我创建了一个HTML扩展来创建一个复选框列表,如下所示:

public static HtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, List<InputItemInfo> ItemInfo)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentException("The argument must have a value", "name");
            if (ItemInfo == null)
                throw new ArgumentNullException("ItemInfo");
            if (ItemInfo.Count < 1)
                throw new ArgumentException("The list must contain at least one value", "ItemInfo");

            StringBuilder sb = new StringBuilder();

            ItemInfo.Insert(0, new InputItemInfo("*", "Select All", ItemInfo.All(i => i.IsChecked)));

            foreach (InputItemInfo info in ItemInfo)
            {
                TagBuilder builder = new TagBuilder("input");
                if (info.IsChecked) builder.MergeAttribute("checked", "checked");
                builder.MergeAttribute("type", "checkbox");
                builder.MergeAttribute("value", info.Value);
                builder.MergeAttribute("name", name);
                builder.InnerHtml = info.DisplayText;
                sb.Append(builder.ToString(TagRenderMode.Normal));
                sb.Append("<br />");
            }

            return new HtmlString(sb.ToString());
        }

我能够在我的视图中使用它,并在控制器中获取值,如下所示:

@model List<AppTest.Models.InputExtensionsViewModel>

@{
    ViewBag.Title = "Check";
}

<h2>Check</h2>

@using (Html.BeginForm())
{
    <table border="0" style="border:0px;">
        <tr>
            <td valign="top">
                @Html.Partial("CheckBoxList", Model[0])
            </td>

        </tr>
    </table>

    <br />

    <input type="submit" value="Go" />
}

<div style="font-weight:bolder">
    @ViewData["data"]
</div>

控制器:

public ActionResult Check()
        {
            var model = new List<InputExtensionsViewModel>();

            var model1 = new InputExtensionsViewModel
            {
                Title = "Facilities",
                InputElementName = "facilities",
                InputElements = // a list
            };

            model.Add(model1);
            return View(model);
       }

    [HttpPost]
    public ActionResult Check(string[] facilities)
    {
               ...
    }

模型是:

public class InputExtensionsViewModel
    {
        public string Title { get; set; }
        public string InputElementName { get; set; }
        public List<InputItemInfo> InputElements { get; set; }

        public void SetSelected(string[] items)
        {
            if (items == null)
                return;

            this.InputElements.ForEach(delegate(InputItemInfo info)
            {
                if (items.Contains(info.Value))
                    info.IsChecked = true;
            });
        }
    }

我的问题是,有没有办法将数组项绑定到InputExtensionsViewModel模型中的属性?如果我只是将一个名为facility的属性添加到视图模型中,它不会自动绑定,我可以理解为什么,因为我在视图中没有绑定。但我似乎无法想出一种可以做到这一点的方法。

此复选框列表是一个用户控件,我只是想避免为我的操作方法使用太多string []数组。

[编辑] - 好的,我现在尝试的时候能做到这一点。不知道为什么它之前没有用。

2)而且,我正在检查替代方案,并在SO中找到了这个答案:

CheckboxList in MVC3.0

我能够复制这个,但我的问题是,如何将标签绑定到此复选框?我的标签是动态的,是模型的一部分,所以不能硬编码。我试图使用Html.LabelFor,但这不起作用。在编辑器模板中,如果我只是@ Model.Text,它将无法工作,并且在回复后将丢失,因为它未绑定到属性

我用谷歌搜索并找到了创建HTML助手的建议,这是我之前所做的(我的第一个问题就是这个)。

如果不清楚,请告诉我。我可以详细说明。任何意见都表示赞赏!

提前致谢!

3 个答案:

答案 0 :(得分:2)

要回答第2部分,您可以轻松地将标签文本添加为​​属性,例如:

public class MyViewModel
{
    public int Id { get; set; }
    public bool IsChecked { get; set; }
    public string Text { get; set; }
}

然后你的模板看起来就像这样:

@model AppName.Models.MyViewModel
@Html.HiddenFor(x => x.Id)           
@Html.CheckBoxFor(x => x.IsChecked)
@Html.LabelFor(x => x.Text)

上述唯一的缺点是标签不会直接链接到复选框。您可以通过执行以下操作来完成此操作:CheckboxList in MVC3

根据重复使用的可能性,您可以像在第一部分中那样创建自己的HtmlHelper,并包含上面粘贴的URL中的建议。

答案 1 :(得分:2)

啊,我找到了解决方案!

1)如我的编辑所示 - 添加一个名称与模型类似的属性,并在[HttpPost]启用的操作方法中使用它可以正常工作。猜猜上次我错过了吸气鬼和安装者。

2)为此,在MyViewModel的编辑器模板中,我们只需要添加它(**和**,不用说,删除**!):

@model AppName.Models.MyViewModel
@Html.HiddenFor(x => x.Id)           
@Html.CheckBoxFor(x => x.IsChecked) **@Model.Text
@Html.HiddenFor(x => x.Text)**

编辑:

我已更改此模板以执行更多操作。现在有一个标签控件,它通过jquery与复选框相关联,如下所示。

@model EncorPlusTest.Infrastructure.InputItemInfo

@Html.HiddenFor(model => model.Value)
@Html.CheckBoxFor(model => model.IsChecked) <label for="">@Model.Text</label>
@Html.HiddenFor(model => model.Text)
<br />

然后在jquery:

$('input:checkbox').each(function () {
        var lbl = $(this).next('input:hidden').next('label');
        var forID = $(this).attr('id');
        $(lbl).attr('for', forID);
    });

希望它对别人有帮助!

答案 2 :(得分:0)

你没有jQuery来解决这个问题。如果用标签包装输入,则会得到相同的行为。

顺便说一句,另一个选项是HTML Helper而不是编辑器模板。看看这个:

public static class HtmlHelperExtensions
{


    #region CheckBoxList

    public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, List<SelectListItem> listInfo)
    {
        return htmlHelper.CheckBoxList(name, listInfo, ((IDictionary<string, object>)null));
    }

    public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, List<SelectListItem> listInfo, object htmlAttributes)
    {
        return htmlHelper.CheckBoxList(name, listInfo, ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
    }

    public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, List<SelectListItem> selectListItems, IDictionary<string, object> htmlAttributes)
    {
        // Verify arguments
        if (String.IsNullOrEmpty(name))
            throw new ArgumentNullException("name", "Name cannot be null");

        if (selectListItems == null)
            throw new ArgumentNullException("selectList", "Select list cannot be null");

        if (selectListItems.Count() < 1)
            throw new ArgumentException("Select list must contain at least one value", "selectList");

        // Define items
        StringBuilder items = new StringBuilder();

        int index = 0;
        // Loop through items)
        foreach (SelectListItem i in selectListItems)
        {
            // hidden value
            TagBuilder hiddenValue = new TagBuilder("input");
            hiddenValue.MergeAttribute("type", "hidden");
            hiddenValue.MergeAttribute("value", i.Value);
            hiddenValue.MergeAttribute("id", string.Format("{0}_{1}__Value", name, index));
            hiddenValue.MergeAttribute("name", string.Format("{0}[{1}].Value", name, index));
            // check box
            TagBuilder checkbox = new TagBuilder("input");
            if (i.Selected)
                checkbox.MergeAttribute("checked", "checked");
            checkbox.MergeAttribute("id", string.Format("{0}_{1}__Selected", name, index));
            checkbox.MergeAttribute("name", string.Format("{0}[{1}].Selected", name, index));
            checkbox.MergeAttribute("type", "checkbox");
            checkbox.MergeAttribute("value", "true");
            // wrapper label
            TagBuilder wrapperLabel = new TagBuilder("label");
            wrapperLabel.InnerHtml = checkbox.ToString(TagRenderMode.SelfClosing);
            wrapperLabel.InnerHtml += i.Text;
            // hidden selected
            TagBuilder hiddenSelected = new TagBuilder("input");
            hiddenSelected.MergeAttribute("type", "hidden");
            hiddenSelected.MergeAttribute("value", i.Selected.ToString().ToLower());
            hiddenSelected.MergeAttribute("name", string.Format("{0}[{1}].Selected", name, index));
            // label for checkbox
            TagBuilder checkBoxLabel = new TagBuilder("label");
            checkBoxLabel.MergeAttribute("for", checkbox.Attributes["id"]);
            checkBoxLabel.MergeAttribute("id", string.Format("{0}_{1}__Text", name, index));
            checkBoxLabel.MergeAttribute("name", string.Format("{0}[{1}].Text", name, index));
            // hidden text
            TagBuilder hiddenText = new TagBuilder("input");
            hiddenText.MergeAttribute("type", "hidden");
            hiddenText.MergeAttribute("value", i.Text);
            hiddenText.MergeAttribute("id", string.Format("{0}_{1}__Text", name, index));
            hiddenText.MergeAttribute("name", string.Format("{0}[{1}].Text", name, index));

            // Add item
            items.AppendLine(hiddenValue.ToString(TagRenderMode.SelfClosing));
            items.AppendLine(wrapperLabel.ToString(TagRenderMode.Normal));
            items.Append(hiddenSelected.ToString(TagRenderMode.SelfClosing));
            items.AppendLine(hiddenText.ToString(TagRenderMode.SelfClosing));

            items.AppendLine();

            index++;
        }

        return MvcHtmlString.Create(items.ToString());
    }
    public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        var name = ExpressionHelper.GetExpressionText(expression);
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return CheckBoxList(htmlHelper, name, metadata.Model as List<SelectListItem>);
    }





    #endregion

}