Как обрабатывать флажки в 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)%> <%= 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 бета, потому что я только что попробовал.
поместите это в представление вместо использования 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
параметр для вас, и даже анализирует строки из запроса.Сформируйте коллекцию в экземпляры объектов GUID, которые, я думаю, скорее милый.
HtmlHelper добавляет скрытый вход для уведомления контроллера о непроверенном состоянии. Поэтому, чтобы иметь правильный проверенный статус:
bool bChecked = form[key].Contains("true");
Если вам интересно, почему они помещают скрытое поле с тем же именем, что и флажок, причина заключается в следующем :
комментарий из исходного кода MVCBetaSource\MVC\src\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)
посетить мой блоге для более подробной информации.
вот что я делаю.
View:
:<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");
@Дилан Битти Отличная Находка!!! Большое вам спасибо. Чтобы расширить еще дальше, этот метод также отлично работает с подходом модели представления. 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; } } }
View:
:<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.
, например,
View:
:<%= 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. Вот и все.
но один вопрос нужно обратить внимание. В каждом компоненте checkbox вы не должны помещать в него "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> <% } %>
это то, что я сделал, чтобы потерять двойные значения при использовании Html.флажок.(..
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-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()" />