【问题标题】:ASP.Net MVC 3 - CheckBoxList - Need some suggestionsASP.Net MVC 3 - CheckBoxList - 需要一些建议
【发布时间】:2011-07-14 14:39:36
【问题描述】:

我对 ASP.Net MVC(和剃须刀)还很陌生,我有几个问题。

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 助手的建议,这就是我之前所做的(我的第一个问题是关于这个的)。

如果有什么不清楚的地方请告诉我。我可以详细说明。任何意见表示赞赏!

提前致谢!

【问题讨论】:

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


    【解决方案1】:

    啊,我找到了解决办法!

    1) 如我的编辑所示 - 将具有相似名称的属性添加到模型并在启用 [HttpPost] 的操作方法中使用它可以正常工作。猜猜我上次错过了 getter 和 setter。

    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);
        });
    

    希望对其他人有所帮助!

    【讨论】:

    • 但是在这种情况下,@Model.Text 的输出 HTML 不会被格式化为 。这是期望的输出吗?
    • 这个只会显示动态文本。我现在即兴创作了一个标签语句,然后用一些 jquery 将它绑定到复选框。我将添加一个编辑!
    【解决方案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 中的建议。

    【讨论】:

    • 感谢您抽出宝贵时间。我确实有一个类似于该链接的 html 帮助程序,我将了解为什么我可以直接映射到 string[] 设施,但不能映射到模型中具有相同名称的属性。但是如果我尝试@Html.LabelFor(x => x.Text),我只会看到“Text”(属性名称)而不是 Text 的值。建议的解决方法是创建一个 html 助手。那么有没有办法做到这一点?
    • 您最好的选择可能是自己滚动,以便更好地控制。我现在不记得(或找不到)LabelFor 的重载。
    【解决方案3】:

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

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

    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
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多