Как обрабатывать флажки в формах 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 ]

4 голосов
/ 23 мая 2012

Исходя из того, что я могу собрать, модель не хочет угадывать, был ли установлен флажок = true или false, я справился с этим, установив атрибут value в элементе checkbox с помощью jQuery, прежде чем отправлять форму следующим образом:

 $('input[type="checkbox"]').each(function () {
       $(this).attr('value', $(this).is(':checked'));
 }); 

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

4 голосов
/ 15 июня 2012

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

Пока я думаю, что делаю все

Contains("true");

вещь отличная и чистая, и работает на всех версиях MVC, проблема в том, что она не учитывает культуру (как будто это действительно имеет значение в случае bool).

«Правильный» способ выяснить значение bool, по крайней мере в MVC3, заключается в использовании ValueProvider.

var value = (bool)ValueProvider.GetValue("key").ConvertTo(typeof(bool));

Я делаю это на одном из сайтов моего клиента, когда редактирую разрешения:

var allPermissionsBase = Request.Params.AllKeys.Where(x => x.Contains("permission_")).ToList();
var allPermissions = new List<KeyValuePair<int, bool>>();

foreach (var key in allPermissionsBase)
{
     // Try to parse the key as int
     int keyAsInt;
     int.TryParse(key.Replace("permission_", ""), out keyAsInt);

     // Try to get the value as bool
     var value = (bool)ValueProvider.GetValue(key).ConvertTo(typeof(bool));
}

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

ValueProvider - это то, что используется при формировании ваших действий следующим образом:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

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

4 голосов
/ 18 января 2010

Эта проблема также возникает в выпуске 1.0. Html.Checkbox () вызывает добавление еще одного скрытого поля с тем же именем / идентификатором, что и у исходного флажка. И когда я пытался загрузить массив флажков с помощью document.GetElemtentsByName (), вы можете догадаться, как все испортилось. Это странно.

3 голосов
/ 11 марта 2014

То же, что и ответ nautic20, просто используйте список флажков привязки модели MVC по умолчанию с тем же именем, что и у свойства коллекции string / int / enum во ViewModel. Вот и все.

Но на одну проблему нужно обратить внимание. В каждом компоненте флажка не следует указывать «Id», который повлияет на привязку модели MVC.

Следующий код будет работать для привязки модели:

 <% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
 <% } %>

Следующие коды не будут привязаны к модели (разница здесь в том, что ей присваивается идентификатор для каждого флажка)

<% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" id="[some unique key]" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
<% } %>
3 голосов
/ 05 января 2012

Самый простой способ сделать это ...

Вы задаете имя и значение.

<input type="checkbox" name="selectedProducts" value="@item.ProductId" />@item.Name

Затем при отправке захватите значения флажков и сохраните их в массиве int. тогда соответствующая функция LinQ. Вот и все ..

[HttpPost]
        public ActionResult Checkbox(int[] selectedObjects)
        {
            var selected = from x in selectedObjects
                           from y in db
                           where y.ObjectId == x
                           select y;                   

            return View(selected);
        }
2 голосов
/ 22 октября 2010

это то, что я сделал, чтобы потерять двойные значения при использовании Html.CheckBox (...

Replace("true,false","true").Split(',')

с 4 флажками, проверено, не проверено, проверено получается правда, ложь, ложь, ложь, истина, ложь в правда, ложь, ложь, правда. только то, что мне нужно

0 голосов
/ 11 ноября 2010

Как насчет этого?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, “Nice try.”);
0 голосов
/ 26 февраля 2014

Используя @mmacaulay, я придумал это для bool:

// MVC Work around for checkboxes.
bool active = (Request.Form["active"] == "on");

Если проверено active = true

Если не отмечено active = false

0 голосов
/ 17 апреля 2013

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

Нашел простое решение, но оно кажется немного грубым.

Попробуйте набрать Viewbag. в вашем контроллере, и теперь вы даете ему имя, например Viewbag.Checkbool

Теперь переключитесь на View и попробуйте это @Viewbag.Checkbool, с этим вы получите значение из контроллера.

Параметры моего контроллера выглядят так:

public ActionResult Anzeigen(int productid = 90, bool islive = true)

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

<input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />
0 голосов
/ 29 декабря 2010

Мое решение:

<input type="checkbox"  id="IsNew-checkbox"  checked="checked" />     
<input type="hidden"  id="IsNew" name="IsNew" value="true"  />      
<script language="javascript" type="text/javascript" >     
  $('#IsNew-checkbox').click(function () {    
      if ($('#IsNew-checkbox').is(':checked')) {    
          $('#IsNew').val('true');    
      } else {    
          $('#IsNew').val('false');    
       }    
  });   
</script>  

Больше вы можете найти здесь: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a-valid-boolean/

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