Как обрабатывать флажки в ASP.NET формы MVC?

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

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

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


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

у меня есть коллекция объектов, и я хочу, чтобы пользователю выбрать один или более из них. Это говорит мне: "форма с флажками."Мои объекты не имеют никакого понятия "selected" (они рудиментарные 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() или через ModelBinder.

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

22 ответов


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

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

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

<% 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 of каждый флажок является идентификатором GUID соответствующего объекта.

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

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 параметр для вас, и даже анализирует строки из запроса.Форма сбора в объекты instantied GUID, который я думаю, довольно милый.


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

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

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

комментарий от исходные коды MVCBetaSource\с MVC\НИЦ\MvcFutures\с MVC\ButtonsAndLinkExtensions.cs

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

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


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

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


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

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

@Dylan Beattie Отличная Находка!!! Я Спасибо. Чтобы расширить еще дальше, этот метод также отлично работает с подходом модели представления. MVC настолько крут, что достаточно умен, чтобы привязать массив GUID к свойству с тем же именем объекта модели, связанного с представлением. Пример:

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

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


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


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

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

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


Я знаю, что этот вопрос был написан, когда 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)

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


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

задать имя и значение.

<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. Вот и все.

но один вопрос нужно обратить внимание. В каждом компоненте флажка вы не должны помещать в него "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>
 <% } %>

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

<% 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.флажок.(..

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

С 4 флажками, непроверенными, непроверенными, проверенными, он поворачивается правда, ложь, ложь, ложь, правда, ложь. в правда, ложь,ложь, правда. как раз то, что мне нужно!--2-->


Как насчет чего-то вроде этого?

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-as-a-valid-boolean/


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

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

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

теперь переключитесь на вид и попробуйте это @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