Подтвердить что ты не робот

Есть ли способ привязать список флажков к модели в asp.net mvc

Я ищу здесь, чтобы найти быстрый и простой способ привязать список элементов списка флажков, когда обратная передача происходит в модели.

По-видимому, общий способ сделать это теперь выглядит так: form.GetValues("checkboxList")[0].Contains("true"); Это кажется болезненным и не совсем безопасным.

Есть ли способ привязать список флажков (которые создаются с помощью или без помощника в представлении) или даже массив данных, который имеет значение во время фазы UpdateModel(myViewModel, form.ToValueProvider());, которая заполняла бы IList<string> или string[] внутри модели?

4b9b3361

Ответ 1

Вы можете начать с модели:

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

тогда контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new[] 
        {
            new MyViewModel { Id = 1, IsChecked = false },
            new MyViewModel { Id = 2, IsChecked = true },
            new MyViewModel { Id = 3, IsChecked = false },
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(IEnumerable<MyViewModel> model)
    {
        // TODO: Handle the user selection here
        ...
    }
}

a Вид (~/Views/Home/Index.aspx):

<% using (Html.BeginForm()) { %>
    <%=Html.EditorForModel() %>
    <input type="submit" value="OK" />
<% } %>

И, наконец, соответствующий шаблон редактора:

<%@ Control 
    Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.MyViewModel>" %>
<%= Html.HiddenFor(x => x.Id) %>
<%= Html.CheckBoxFor(x => x.IsChecked) %>

Теперь, когда вы отправляете форму в действии POST, вы получите список выбранных значений вместе с их идентификатором.

Ответ 2

Вот быстрый и простой способ. Просто установите атрибут value внутри своих входных элементов checkbox и дайте им все то же самое name. Если бы я реализовал это на сайте, я бы создал вспомогательный метод checkbox, который принимает параметры name, value и isChecked, но здесь View с помощью только необходимого html:

<% using (Html.BeginForm()) { %>
  <p><input type="checkbox" name="checkboxList" value="Value A" /> Value A</p>
  <p><input type="checkbox" name="checkboxList" value="Value B" /> Value B</p>
  <p><input type="checkbox" name="checkboxList" value="Value C" /> Value C</p>
  <p><input type="checkbox" name="checkboxList" value="Value D" /> Value D</p>
  <p><input type="checkbox" name="checkboxList" value="Value E" /> Value E</p>
  <p><input type="checkbox" name="checkboxList" value="Value F" /> Value F</p>
  <input type="submit" value="OK" />
<% } %>

В вашем контроллере:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(IEnumerable<string> checkboxList)
{
    if (checkboxList != null)
    {
        ViewData["Message"] = "You selected " + checkboxList.Aggregate("", (a, b) => a + " " + b);
    }
    else
    {
        ViewData["Message"] = "You didn't select anything.";
    }

    return View();
}

Параметр IEnumerable<string> (вы можете сделать его IList<string>, если хотите) будет содержать только значения отмеченных элементов. Это будет null, если ни один из ящиков не установлен.

Ответ 3

Это работает очень хорошо, используя настраиваемое связующее устройство и обычный HTML...

Во-первых, ваша форма HTML в синтаксисе Razor:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) {
    <ol>
        <li><input type="textbox" name="tBox" value="example of another form element" /></li>

        <li><input type="checkbox" name="cBox" value="1" /> One</li>
        <li><input type="checkbox" name="cBox" value="2" /> Two</li>
        <li><input type="checkbox" name="cBox" value="3" /> Three</li>
        <li><input type="checkbox" name="cBox" value="4" /> Four</li>
        <li><input type="checkbox" name="cBox" value="5" /> Five</li>

        <li><input type="submit" /></li>
    </ol>
}

(FormMethod.Post также может быть .Get, для этого не имеет значения)

Затем в собственном смысле MVC есть объект модели, который представляет вашу форму:

public class CheckboxListExampleModel {
    public string TextboxValue { get; set; }
    public List<int> CheckboxValues { get; set; }
}

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

public class CheckboxListExampleModel {
    public string TextboxValue { get; private set; }
    public List<int> CheckboxValues { get; private set; }

    public class Binder : DefaultModelBinder {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
            var model = new CheckboxListExampleModel();

            model.TextboxValue = bindingContext.GetValueAsString("tBox");

            string checkboxCsv = bindingContext.GetValueAsString("cBox");
            // checkboxCsv will be a comma-separated list of the 'value' attributes
            //   of all the checkboxes with name "cBox" which were checked
            model.CheckboxValues = checkboxCsv.SplitCsv<int>();

            return model;
        }
    }
}

.GetValueAsString() - это метод расширения, используемый для ясности, вот он:

    public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) {
        var providerResult = context.ValueProvider.GetValue(formValueName);
        if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) {
            if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) {
                return null;
            } else {
                return providerResult.AttemptedValue.Trim();
            }
        }
        return null;
    }

.SplitCsv<T>() также является методом расширения, но он достаточно распространен и требует довольно грязного кода, который я оставил ему как упражнение для читателя.

И, наконец, ваше действие для обработки формы submit:

[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) {
    // stuff
}