Как обрабатывать флажки в формах ASP.NET MVC? - PullRequest
247 голосов
/ 21 октября 2008

Внимание: этому вопросу больше девяти лет!

Ваш лучший вариант - искать новые вопросы или искать ответы ниже, чтобы найти вашу конкретную версию MVC, так как многие ответы здесь устарели.

Если вы найдете ответ, который подходит для вашей версии, убедитесь, что в ответе содержится версия MVC, которую вы используете.
(оригинальный вопрос начинается ниже)


Мне это кажется немного странным, но, насколько я могу судить, именно так вы и делаете.

У меня есть коллекция объектов, и я хочу, чтобы пользователи выбирали один или несколько из них. Это говорит мне "форма с флажками". Мои объекты не имеют никакого понятия «выбранный» (они элементарные POCO, сформированные путем десериализации вызова wcf). Итак, я делаю следующее:

public class SampleObject{
  public Guid Id {get;set;}
  public string Name {get;set;}
}

В виде:

<%
    using (Html.BeginForm())
    {
%>
  <%foreach (var o in ViewData.Model) {%>
    <%=Html.CheckBox(o.Id)%>&nbsp;<%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

И, в контроллере, это единственный способ выяснить, какие объекты проверял пользователь:

public ActionResult ThisLooksWeird(FormCollection result)
{
  var winnars = from x in result.AllKeys
          where result[x] != "false"
          select x;
  // yadda
}

Во-первых, он причудливый, а во-вторых, для тех элементов, которые проверял пользователь, FormCollection отображает его значение как «истинное ложное», а не просто истинное.

Очевидно, я что-то упустил. Я думаю, что это построено с мыслью о том, что объекты в коллекции, которые обрабатываются в html-форме, обновляются с помощью UpdateModel() или через ModelBinder.

Но мои объекты не созданы для этого; Значит ли это, что это единственный путь? Есть ли другой способ сделать это?

Ответы [ 22 ]

262 голосов
/ 21 октября 2008

Html.CheckBox делает что-то странное - если вы посмотрите на исходную страницу источник, вы увидите, что <input type="hidden" /> генерируется рядом с каждым флажком, что объясняет "истинные ложные" значения, которые вы видите для каждой формы элемент.

Попробуйте это, что определенно работает на ASP.NET MVC Beta, потому что я только что попробовал.

Поместите это в представление вместо использования Html.CheckBox ():

<% using (Html.BeginForm("ShowData", "Home")) {  %>
  <% foreach (var o in ViewData.Model) { %>
    <input type="checkbox" name="selectedObjects" value="<%=o.Id%>">
    <%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

Все ваши флажки называются selectedObjects, а value каждого флажка является GUID соответствующего объекта.

Затем опубликуйте следующее действие контроллера (или что-то подобное, что делает что-то полезное вместо Response.Write ())

public ActionResult ShowData(Guid[] selectedObjects) {
    foreach (Guid guid in selectedObjects) {
        Response.Write(guid.ToString());
    }
    Response.End();
    return (new EmptyResult());
}

Этот пример просто напишет GUID ящиков, которые вы отметили; ASP.NET MVC отображает значения GUID выбранных флажков в параметр Guid[] selectedObjects и даже анализирует строки из коллекции Request.Form в экземпляры объектов GUID, что, на мой взгляд, довольно неплохо.

95 голосов
/ 12 января 2009

HtmlHelper добавляет скрытый ввод для уведомления контроллера о статусе Unchecked. Таким образом, чтобы иметь правильный проверенный статус:

bool bChecked = form[key].Contains("true");
54 голосов
/ 26 января 2009

Если вам интересно, ПОЧЕМУ они вставили скрытое поле с тем же именем, что и флажок, причина заключается в следующем:

Комментарий из исходного кода MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

Предоставьте дополнительные <input type="hidden".../> для флажков. Это касается сценариев, где снятые флажки не отправляются в запрос. Отправка скрытого ввода позволяет узнать, что флажок присутствовал на странице, когда запрос был отправлен.

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

49 голосов
/ 26 января 2009

Вы также должны использовать <label for="checkbox1">Checkbox 1</label>, потому что тогда люди могут нажимать на текст метки, а также на сам флажок. Его также легче стилизовать, и, по крайней мере, в IE он будет выделен при переходе по элементам управления страницы.

<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>

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

27 голосов
/ 16 октября 2011

Я удивлен, что ни один из этих ответов не использовал для этого встроенные функции MVC.

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

Вы просто получите новый файл в папке EditorTemplate, который выглядит следующим образом:

@model SampleObject

@Html.CheckBoxFor(m => m.IsChecked)
@Html.HiddenFor(m => m.Id)
@Html.LabelFor(m => m.IsChecked, Model.Id)

на самом деле, вам не нужно будет это зацикливать, просто 1 строка кода:

@Html.EditorFor(x => ViewData.Model)

Посетите мой пост в блоге для более подробной информации.

25 голосов
/ 21 октября 2008

Вот что я делал.

Вид:


<input type="checkbox" name="applyChanges" />

Контроллер:


var checkBox = Request.Form["applyChanges"];

if (checkBox == "on")
{
...
}

Я нашел вспомогательные методы Html. * В некоторых случаях не очень полезными, и мне было бы лучше делать это в простом старом HTML. Это один из них, другой, который приходит на ум, это радио-кнопки.

Edit: это в Preview 5, очевидно, YMMV между версиями.

10 голосов
/ 20 марта 2010

Похоже, что они выбирают чтение только первого значения, поэтому это «истина», когда флажок установлен, и «ложь», когда включено только скрытое значение. Это легко получить с помощью следующего кода:

model.Property = collection["ElementId"].ToLower().StartsWith("true");
8 голосов
/ 04 июня 2010

@ Дилан Битти Отличная находка !!! Большое спасибо Чтобы еще больше расширить этот метод, он также прекрасно работает с подходом View Model. MVC настолько крут, что достаточно умен, чтобы привязать массив Guids к свойству с тем же именем объекта Model, привязанного к View. Пример:

ViewModel:

public class SampleViewModel
{
    public IList<SampleObject> SampleObjectList { get; set; }
    public Guid[] SelectedObjectIds { get; set; }

    public class SampleObject
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
}

Вид:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Sample View</h2>
<table>
    <thead> 
        <tr>
            <th>Checked</th>
            <th>Object Name</th>
        </tr>
    </thead> 
<% using (Html.BeginForm()) %>
<%{%>                    
    <tbody>
        <% foreach (var item in Model.SampleObjectList)
           { %>
            <tr>
                <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
                <td><%= Html.Encode(item.Name)%></td>
            </tr>
        <% } %>
    </tbody>
</table>
<input type="submit" value="Submit" />
<%}%>                    

Контроллер:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult SampleView(Guid id)
    {
        //Object to pass any input objects to the View Model Builder 
        BuilderIO viewModelBuilderInput = new BuilderIO();

        //The View Model Builder is a conglomerate of repositories and methods used to Construct a View Model out of Business Objects
        SampleViewModel viewModel = sampleViewModelBuilder.Build(viewModelBuilderInput);

        return View("SampleView", viewModel);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SampleView(SampleViewModel viewModel)
    {
        // The array of Guids successfully bound to the SelectedObjectIds property of the View Model!
        return View();
    }

Любой, кто знаком с философией View Model, будет рад, это работает как Champ!

6 голосов
/ 22 марта 2010

Я также хотел бы отметить, что вы можете присвоить каждому флажку свое имя и включить его в параметры actionresults.

Пример,

Просмотр:

 <%= Html.CheckBox("Rs232CheckBox", false, new { @id = "rs232" })%>RS-232

 <%= Html.CheckBox("Rs422CheckBox", false, new { @id = "rs422" })%>RS-422

Контроллер:

public ActionResults MyAction(bool Rs232CheckBox, bool Rs422CheckBox) {
    ...
}

Значения из представления передаются действию, поскольку имена совпадают.

Я знаю, что это решение не идеально подходит для вашего проекта, но я подумал, что смогу реализовать эту идею.

5 голосов
/ 21 июня 2010
<input type = "checkbox" name = "checkbox1" /> <label> Check to say hi.</label>

с контроллера:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection fc)
    {

         var s = fc["checkbox1"];

         if (s == "on")
         {
             string x = "Hi";
         }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...