ASP.Net MVC 3 - CheckBoxList - нужны предложения - PullRequest
1 голос
/ 14 июля 2011

Я довольно новичок в 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? Если я просто добавлю свойство под названием средства в модель представления, оно не будет привязано автоматически, и я пойму почему, поскольку я не связываю это с моим представлением. Но я не могу придумать, каким образом я мог бы это сделать.

Этот список флажков является пользовательским элементом управления, и я просто хотел избежать использования слишком большого массива string [] для моих методов действия.

[РЕДАКТИРОВАТЬ] - Хорошо, я смог сделать это, когда я попробовал сейчас. Не уверен, почему это не сработало раньше.

2) И, я проверял альтернативы и нашел этот ответ в SO:

CheckboxList в MVC3.0

И я смог повторить это, но мой вопрос, как мне привязать ярлык к этому флажку? Мои метки являются динамическими и являются частью модели и поэтому не могут быть жестко закодированы. Я пытался использовать Html.LabelFor, но это не сработало. В шаблоне редактора, если я просто @ Model.Text, он не будет работать и будет потерян после обратной передачи, так как он не привязан к свойству

Я гуглил и нашел предложения по созданию помощников HTML, что я и делал ранее (мой первый вопрос об этом).

Пожалуйста, дайте мне знать, если что-то неясно. Я мог бы уточнить. Любой вклад приветствуется!

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 15 июля 2011

Ах, я нашел решение!

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)**

EDIT:

Я изменил этот шаблон, чтобы сделать больше. Теперь есть элемент управления меткой, и он связан с флажками через 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 голосов
/ 14 июля 2011

Чтобы ответить на часть 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 в MVC3

В зависимости от шансов на повторное использование, вы всегда можете создать свой собственный HtmlHelper, как вы делали в первой частиэто и включите предложения из URL, который я вставил выше.

0 голосов
/ 30 августа 2012

Вы не решаете эту проблему. Если обернуть ввод меткой, вы получите то же поведение.

Кстати, другой вариант, вместо шаблона редактора, - это 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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...