Вопрос

Осторожно:Этому вопросу больше девяти лет!

Ваш лучший вариант - выполнить поиск новых вопросов или найти ответы ниже в поисках вашей конкретной версии 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 выводит свое значение как "true false", а не просто true.

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

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

Это было полезно?

Решение

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

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

Поместите это в представление вместо использования 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, что, на мой взгляд, довольно неплохо.

Другие советы

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

bool bChecked = form[key].Contains("true");

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

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

  

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

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

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

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

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

Я удивлен, что ни один из этих ответов не использовал для этого встроенные функции 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)

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

Вот что я делал в последнее время.

Вид:


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

Контроллер:


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

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

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

Редактировать:это в предварительном просмотре 5, очевидно, YMMV между версиями.

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

model.Property = collection["ElementId"].ToLower().StartsWith("true");

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

Видовая модель:

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, будет радоваться, это работает как чемпион!

Я также хотел бы отметить, что вы можете присвоить каждому флажку другое имя и включить это имя в параметры 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) {
    ...
}

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

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

<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";
         }
    }

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

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

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

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

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

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

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 во время компиляции, поэтому вам придется обрабатывать их на лету.

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

Вы сами устанавливаете имя и значение.

<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);
        }

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

Но на одну проблему нужно обратить внимание. В каждом компоненте флажка не следует ставить & Quot; Id & Quot; в нем, что повлияет на привязку модели 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>
<% } %>

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

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

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

Как насчет чего-то подобного?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, “Nice try.”);

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

Таким образом, проверка «проверено» или «верно» будет такой:

//looking for [true],[false]
bool isChecked = form.GetValues(key).Contains("true"); 

Выполнение ложной проверки будет следующим:

//looking for [false],[false] or [false]
bool isNotChecked = !form.GetValues(key).Contains("true"); 

Основное отличие заключается в использовании GetValues, поскольку это возвращает в виде массива.

Просто сделайте это на $(document).ready:

$('input:hidden').each(function(el) {
    var that = $(this)[0];
    if(that.id.length < 1 ) {

        console.log(that.id);
        that.parentElement.removeChild(that);

    }
});

Мое решение:

<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- как-уважительной-булевы /

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

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

Попробуйте ввести 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()" />

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top