Есть ли способ привязать список флажков к модели в asp.net mvc - PullRequest
12 голосов
/ 03 февраля 2011

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

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

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

Ответы [ 3 ]

9 голосов
/ 25 марта 2011

Вот быстрый и простой способ.Просто установите атрибут value внутри ваших checkbox элементов ввода и присвойте им все те же name. Если бы я реализовывал это на сайте, я бы создал вспомогательный метод CheckBox, который принимает параметры name, value и isChecked , но вот представление с необходимым 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, если ни один из флажков не установлен.

9 голосов
/ 04 февраля 2011

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

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, вы получите список выбранных значений вместе с их идентификатором.

0 голосов
/ 12 марта 2015

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

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

[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) {
    // stuff
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...