Как сопоставить флажки с элементами модели MVC?

У меня есть MVC-представление

<%@ Page Language="C#" MasterPageFile="PathToMaster" Inherits="System.Web.Mvc.ViewPage<ModelData>" %>

и у меня есть форма с разметкой HTML для набора флажков:

<label for="MyCheckbox">Your choice</label>
<input type="checkbox" id="Option1" class="checkbox" name="MyCheckbox" value="Option one" />
<label for="Option1">Option one</label><br />
<input type="checkbox" id="Option2" class="checkbox" name="MyCheckbox" value="Option two" />
<label for="Option2">Option two</label><br />

и у меня есть пара управляющих действий

class MyController : Controller {
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult RequestStuff( ModelData data )
    {
    }
}

и это действие вызывается при отправке формы.

Как сопоставить флажки с элементами ModelData (и какие элементы я должен добавить в ModelData), чтобы при отправке формы data хранилась информация о том, какие флажки отмечены?

Ответ 1

ОК, этот будет для MVC3, но - сохранить изменения синтаксиса - должен работать и в MVC2. Подход, по сути, один и тот же.

Прежде всего, вы должны подготовить подходящую (View) модель

public class MyViewModel
{
    [DisplayName("Option 1")]
    public bool Option1 { get; set; }

    [DisplayName("Option 2")]
    public bool Option2 { get; set; }
}

Затем вы передаете эту модель в представление, которое вы показываете (контроллер):

public ActionResult EditMyForm()
{
    var viewModel = new MyViewModel()
    return View(viewModel);
}

с формой:

@model MyViewModel
@using( Html.BeginForm())
{
    @Html.Label("Your choice")

    @Html.LabelFor(model => model.Option1) // here the 'LabelFor' will show you the name you set with DisplayName attribute
    @Html.CheckBoxFor(model => model.Option1)

    @Html.LabelFor(model => model.Option2)
    @Html.CheckBoxFor(model => model.Option2)
    <p>
        <input type="submit" value="Submit"/>
    </p>
}

Теперь здесь помощники HTML (все CheckBoxFor, LabelFor, EditorFor и т.д.) позволяют привязать данные к свойствам модели.

Теперь помните, что EditorFor, когда свойство имеет тип bool, также даст вам флажок в представлении.:)

И затем, когда вы отправляете контроллер, он автоматически привяжет значения:

[HttpPost]
public ActionResult EditMyForm(MyViewModel viewModel)
{
    //And here the view model items will be set to true/false, depending what you checked.
}

Ответ 2

Сначала вы определяете SelectList для параметров. Это будет использоваться для рендеринга флажков

    public IList<SelectListItem> OptionsSelectList { get; set; }

Чем вы определяете модель, которая будет удерживать значение одного выбранного варианта после сообщения

public class ChooseOptionViewModel
{
    public int OptionIdentifier { get; set; } //name or id
    public bool HasBeenChosen { get; set; } //this is mapped to checkbox
}

Затем IList этих опций в ModelData

public IList<ChooseOptionViewModel> Options { get; set; }

И, наконец, представление

    @for (int i = 0; i < Model.OptionsSelectList.Count(); i++)
    {
        <tr>
            <td class="hidden">
                @Html.Hidden("Options[" + i + "].OptionIdentifier", Model.OptionsSelectList[i].Value)
            </td>
            <td>
                @Model.OptionsSelectList[i].Text
            </td>
            <td>
                @Html.CheckBox("Options[" + i + "].HasBeenChosen", Model.Options != null && Model.Options.Any(x => x.OptionIdentifier.ToString().Equals(Model.OptionsSelectList[i].Value) && x.HasBeenChosen))
            </td>
        </tr>
    }

После публикации вы просто проверяете Options.Where(x => x.HasBeenChosen)

Это полнофункционально, и это позволит вам повторно отображать представление при возникновении ошибок проверки и т.д. Это кажется немного сложным, но я не придумал лучшего решения, чем это.