Не удается привязать html.checkbox к сообщению формы

#asp.net-mvc #asp.net-mvc-3

#asp.net-mvc #asp.net-mvc-3

Вопрос:

Итак, у меня есть вызов модели представления ProductViewModel, который содержит список сайтов, на которых может быть произведен продукт. Я пытаюсь выяснить, как отобразить это в форме, используя флажок, позволяющий пользователю выбирать сайты, на которых может быть произведен продукт. Кажется простым, не так ли? Ну, это работает не так, как я хочу / нужно. Надеюсь, кто-нибудь может помочь мне указать правильный способ сделать это.

Мои классы:

  public class ProductViewModel
 {
    public List<Sites> SiteList {get; set;}   
    public string ProductName {get; set;}
    public int ProductId {get; set;}
    public User ProductOwner{get; set;}
 }

 public class Sites
 { 
    public int SiteId {get; set;} 
    public string SiteName {get; set;}
    public bool IsSelected {get; set;}    
 }
  

Часть моего представления:

 @Html.LabelFor(m=>m.Sites):
@foreach (var site in Model.Sites)
{
    @Html.CheckBox("Sites", site.IsSelected, new { value = site.SiteName })
    @Html.Label(site.SiteName)
} 
  

При использовании @Html.Checkbox () Я вижу следующий вывод в html из браузера:

 <input checked="checked" id="Sites" name="Sites" type="checkbox" value="Miami" />
<input name="Sites" type="hidden" value="false" />
  

Я понимаю скрытое поле, но что мне действительно нужно, так это получить значение для выбранного элемента. Итак, мне нужно вернуть список с Майами в нем. Мне не нужны значения false / true, которые, похоже, хочет отправить помощник html (т. Е. Miami = true)

Поэтому вместо этого я попробовал это.

 @for(int id=0; id < Model.Sites.Count(); id  )
{
    <input type="checkbox" id="@Model.Sites[id].SiteName" name="Sites[@id]" value="@Model.BoxingSites[id].SiteName" @(Model.Sites[id].IsSelected  ? @"checked=""checked""": "") />
    @Html.Label(Model.Sites[id].SiteName)                   
}  
  

И вывод такой:

 <input type="checkbox" id="Miami" name="Sites[0]" value="Miami" checked=amp;quot;checkedamp;quot; />
<label for="Miami">Miami</label>
  

В обоих этих случаях я не могу заставить связующее средство сопоставить значения формы с продуктом.Список сайтов при публикации в действие.

Действие выглядит следующим образом:

 [HttpPost]
public ActionResult Edit(ProductViewModel Product)
{
     //Does something with the form data.
}
  

Другие значения (ProductName и т.д. …) Отображаются нормально.

Что я делаю не так? Я чувствую, что чего-то не хватает, поскольку это должно быть проще из-за того, как MVC упрощает множество других ситуаций с обработкой форм.

Заранее спасибо…

Комментарии:

1. вы также могли бы использовать помощник checkboxlist отсюда awesome.codeplex.com

2. @Omu — Спасибо за ссылку. Это действительно потрясающе. Я определенно буду использовать это и для некоторых других нужд.

Ответ №1:

Как насчет использования шаблона редактора вместо того, чтобы бороться с циклами:

 @model ProductViewModel
@using (Html.BeginForm())
{
    ... some other form fields

    @Html.LabelFor(x => x.SiteList)
    @Html.EditorFor(x => x.SiteList)

    <input type="submit" value="Create" />
}
  

и внутри соответствующего шаблона редактора ~/Views/Shared/EditorTemplates/Sites.cshtml :

 @model Sites
<div>
    @Html.HiddenFor(x => x.SiteId)
    @Html.CheckBoxFor(x => x.IsSelected)
    @Html.LabelFor(x => x.SiteName)
</div>
  

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

 [HttpPost]
public ActionResult Create(ProductViewModel model)
{
    ...
}
  

Комментарии:

1. Вы только что показали мне отличный пример того, когда использовать шаблон. Это работает; однако я вижу странную проблему с ярлыком. @Html.LabelFor(x=>x.SiteName) отправляет «SiteName», а не «Miami» Есть идеи, почему?

2. О, я также заметил другие проблемы. При публикации сопоставление для SiteID, IsSelected работает, но SiteName равно null. Даже после переключения на @Html.Label (модель. Имя сайта).

3. @Racter, это значение равно нулю, потому что оно никогда не отправлялось на сервер. Вы могли бы включить его в качестве скрытого поля внутри шаблона: @Html.HiddenFor(x => x.SiteName) , так же, как вы сделали с SiteId . Что касается вашего первого вопроса, вы могли бы заменить @Html.LabelFor(x => x.SiteName) на @Html.DisplayFor(x => x.SiteName) , если хотите отобразить значение.

Ответ №2:

Вот что работает у меня.

 // View Model
[Display(Name="Boolean Property")]
[UIHint("booleancheckbox"]
public bool? booleanProperty;
  

Вид

 // View
@Html.EditorFor(m => m.booleanProperty, new { @onclick = "Toggle(this);" })
  

Шаблон редактора — добавьте еще немного кода для обработки нулевых значений

 // Editor Template booleancheckbox.cshtml
@model bool?

@{
    labelText = ViewData.ModelMetadata.DisplayName != null ?
                ViewData.ModelMetadata.DisplayName : 
                ViewData.ModelMetadata.PropertyName;
}

<label for="@ViewData.ModelMetadata.PropertyName">@labelText

    @Html.CheckBox(string.Empty, Model.Value, ViewContext.ViewData)

</label>