2014-11-26 2 views
-2

я следующая формой в виде:Использования CheckBoxFor в форме

@using (Html.BeginForm("Subscriptions", "Group", new { id = Model.Id, slug = Model.Slug, Groups = Model.Groups, Names = Model.SelectedNames, SelectedMemberEmail = Model.SelectedMember.EmailAddress, WhichView = "Subscriptions", }, FormMethod.Post)) 
    { 
    <div id="communitygroupsedit" class="list-unstyled"> 
     @for (var x = 0; x < Model.Groups.Count; x++) 
      { 
      if (Model.Groups[x].Name == "All members") 
       { 
        Model.Groups[x].AdminOnly = true; 
       } 
      string adminTest = (Model.Groups[x].AdminOnly && !Model.IsUserAdministrator) ? "disabled=\"disabled\"" : string.Empty; 
      string checktest = Model.Groups[x].IsMember ? "checked=\"checked\"" : string.Empty; 

      <p> 
       @Html.CheckBoxFor(m => m.Groups[x].IsMember, new { @adminTest @checktest}) 
       @Html.Raw(Model.Groups[x].Name + " - " + Model.Groups[x].Description) 
       @if (adminTest == "disabled=\"disabled\"" && !Model.IsUserAdministrator && checktest == "checked=\"checked\"") 
       { 
        Model.SelectedNames.Add(Model.Groups[x].Name); 
       }       
      </p> 
     } 
     </div> 
    if (Model.Groups.Count > 0) 
    { 
     @Html.SubmitButton("Update groups", false, new { @class = "btn btn-primary" }); 
     } 

Проблема заключается в том, что в контроллере, «Группа» список объекты пусты, и в представлении, флажки не быть если условие выполнено. Также свойство selectednames не заполняет список «Имена» по мере необходимости. Что я делаю неправильно в этой форме?

+0

ИМХО вы делаете так много обработки в представлении, трудно понять, что происходит. Такие вещи, как adminTest & checktest, действительно должны быть в контроллере. – markpsmith

ответ

1

Что я делаю неправильно в этой форме?Все!

А почему вы не получаете SelectedNames, вы не делаете какие-либо элементов управления для него так, как бы что-нибудь опубликовать назад

Если вы посмотрите на атрибуте тега <form>action и это должно быть очевидно. Это будет что-то вроде

<form action="/Group/Subscriptions.....?Names=System.Collections.Generic.List%601%5BYourAssembly.YourModelName%5D" ....> 

так, когда вы размещаете форму, свойство SelectedNames является строкой "System.Collections.Generic.List...", которая наклоняет быть привязана к коллекции.

Теперь проверьте HTML для галочки, вы увидите что-то вроде (в зависимости от значений adminTest и checktest

<input type="checkbox" ... adminTest="" checktest="checked="checked""> 

, который, конечно, не устанавливающих disabled или checked атрибутов флажка. Даже если вы сделали это правильно, и флажок был отключен и отмечен (true), он отправит обратно значение false (отключенные флажки не возвращают, поэтому ModelBinder будет привязываться к false из-за связанного скрытого ввода), и вы получите неверные данные.

Когда вы используете @Html.CheckBoxFor(m => m.Groups[x].IsMember), состояние флажка установлено на основании значения IsMember, поэтому код string checktest = Model.Groups[x].IsMember ? "checked=\"checked\"" : string.Empty; не только ошибочен, но и совершенно бессмысленен.

И в чем смысл if (Model.Groups.Count > 0)? Единственное, что вы редактируете, это Groups, поэтому, если их нет, почему бы отобразить пустую форму, которая не может быть отправлена!

Удалить все это и создать модель представления для отображения/редактирования, что вы хотите

View Model

public class GroupVM 
{ 
    public int ID { get; set; } 
    public string DisplayName { get; set; } 
    public bool IsMember { get; set; } 
} 

public class MyModelVM 
{ 
    public int ID {get; set; } 
    // any other properties of the model you want to display 
    public List<GroupVM> Groups { get; set; } 
} 

Контроллер

public ActionResult Group(int ID) 
{ 
    // Get your data model 
    .... 
    MyModelVM model = new MyModelVM(); 
    model.Groups = new List<GroupVM>(); 
    // Populate the collection based on your data model 
    foreach(var item in yourDataModel.Groups) 
    { 
    GroupVM group = new GroupVM(); 
    // apply you logic here 
    if(item.AdminOnly && !item.IsUserAdministrator) 
    { 
     continue; // no point displaying these 
    } 
    group.ID = item.ID; 
    group.DisplayName = string.Format("{0} - {1}", item.Name, item.Description) 
    group.IsMember = item.IsMember; 
    model.Groups.Add(group); 
    } 
    if (model.Groups.Count == 0) 
    { 
    // ?? is there any point displaying a form? 
    } 
    return View(model); 
} 

Просмотр

@model MyModelVM 
@using (Html.BeginForm()) 
{ 
    for(int i = 0; i < Model.Groups.Count; i++) 
    { 
    @Html.HiddenFor(m => m.Groups[i].ID) 
    @Html.CheckBoxFor(m => m.Groups[i].IsMember) 
    @Html.LabelFor(m => m.Groups[i].DisplayName) 
    } 
    <input type="submit" value="Update groups" /> 
} 

POST мето d

public ActionResult Group(MyModel model) 
{ 
    // The model contains the ID so get the data model from the database 
    // and loop model.Groups to update the data model and save 
} 
+0

Большое спасибо за подробный ответ Стивен. Как вы, возможно, догадались, программирование - это очень новая вещь для меня, и я часто нахожу ее очень запутанной, и мне приходится много догадываться. Я очень с нетерпением жду подробного рассмотрения вашего решения. – Jynn

-1

Я взволнован, чтобы сказать, что я, наконец, получил его работу. Стивен, ваш пост показал, что я не понимаю, как должна работать форма, поскольку я думал, что вы можете просто передать какое-либо старое значение оттуда к контроллеру.Ваше решение, к сожалению, не сработало бы для меня, поскольку я все еще хотел отображать флажок в состоянии только для чтения, если был флажок «adminOnly», и ваш код вообще не отображал бы его.

У меня возникла проблема с checkboxfor, возвращающая false, если она была отключена, просто выделив флажок так, как я хотел, а затем с помощью hiddenfor вернул состояние окна.
Еще одна вещь, которую вы задали, - это то, что является точкой if (groups.count> 0) .show submit. Это потому что, если нет групп, я не хочу, чтобы кнопка отправки была визуализирована.

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

Это то, что я придумал:

@using (Html.BeginForm("Subscriptions", "Group", FormMethod.Post)) 
    { 
     <div id="communitygroupsedit" class="list-unstyled"> 
      <p> @if (Model.Groups[x].AdminOnly) 
       { 
        string adminTest = (Model.Groups[x].AdminOnly && !Model.IsUserAdministrator) ? "disabled=\"disabled\"" : string.Empty; 
        string checktest = Model.Groups[x].IsMember ? "checked=\"checked\"" : string.Empty; 
        <input type="checkbox" @adminTest @checktest /> 

        @Html.HiddenFor(m => m.Groups[x].IsMember) 
        @Html.HiddenFor(m => m.Groups[x].Name) 
        @Html.HiddenFor(m => m.Groups[x].AdminOnly) 
       } 
       else 
       { 
        @Html.CheckBoxFor(m => m.Groups[x].IsMember) 
       @Html.HiddenFor(m => m.Groups[x].Name) 
       @Html.HiddenFor(m => m.Groups[x].AdminOnly) 
       } 
       @Html.Raw(Model.Groups[x].Name + " - " + Model.Groups[x].Description) 
              </p> 
       } 
      </div> 
      if (Model.Groups.Count > 0) 
      { 
      @Html.SubmitButton("Update groups", false, new { @class = "btn btn-primary" }); 
      } 
     } 

В контроллере:

List<string> Names = new List<string>(); 
foreach (var group in input.Groups) 
    { 
    if (group.IsMember) 
    Names.Add(group.Name); 
    } 

... написать в базу данных

+0

Вы все еще не получаете MVC или Http. Нет такой вещи, как checkonly checkbox - просто отобразите «Да» или «Нет» (или подобное). Вы не должны предоставлять скрытые входы для данных, которые вы не изменяете. Вы открываете себя для перенаправления атак и отправки большого количества данных клиенту, а затем обратно без изменений просто ухудшает производительность - просто получите его из базы данных в методе POST, если вам нужно. И насколько 'if (groups.count> 0)' - почему вы когда-либо возвращали представление в первую очередь, если бы не было групп для отображения, поэтому 'if' бессмысленно. –

Смежные вопросы