2013-03-07 2 views
1

У меня есть это представление, основанное на списке модели, где я создаю строго типизированные флажки для каждого элемента модели на основе логического.Как создать список объектов на основе checkboxfor, созданных для модели

Вот мое мнение:

@using MyApp.Models 
@model IList<MyApp.Models.ObjInfo> 

@{ 
    ViewBag.Title = "Obj Inventory"; 
} 

<h2>Search Inventory</h2> 

<p> 
    @using (Html.BeginForm()) 
    { 
     (Many search filters which are non-relevant) 
     <p> 
      Send Items: @Html.ActionLink("Click Here", "SendItems") 
     </p> 
    } 
<table> 
    <tr> 
     <th> 
      Obj Name 
     </th> 
     <th> 
      Number In Stock 
     </th> 
     (...) 
     <th> 
      Select Item 
     </th> 
    </tr> 
@foreach (var item in Model) { 
    <tr> 
     <td> 
      @Html.DisplayFor(modelItem => item.OtherObj.m_Name) 
     </td> 
     (...) 
     <td> 
      @Html.CheckBoxFor(modelItem => item.m_IsSelected) 
     </td> 
    </tr> 
} 

</table> 

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

Теперь мой вопрос в том, что я хочу создать список, который будет группировать только элементы в списке, которые проверяются, и отправлять их на контроллер. Как я мог это сделать? Может ли кто-нибудь помочь мне или предложить мне способ работать?

Спасибо!

* EDIT *

Вот метод HttpPost используется для получения списка элементов, как указано ниже:

// 
     // GET: /Inventory/SendItems 
     [HttpPost] 
     public ActionResult SendItems(IList<ObjInfo> listToSend) 
     { 
      m_ListObjToSend = new List<ObjInfo>(); 

      foreach (var item in listToSend.Where(item => item.m_IsSelected)) 
      { 
       m_ListObjToSend .Add(item); 
      } 

      return View(m_ListObjToSend); 
     } 

Однако я столкнулся с множеством проблем:

  • Это метод НЕ работает, если я помещаю атрибут [HttpPost] (он будет отображаться как «Not Found»);
    • Список, который я должен получать, имеет значение NULL;
    • Каждое скрытое поле, связанное с флажком, имеет значение по умолчанию как false, даже если проверенное значение показывает true;
    • Я использую actionlink, потому что я не хочу использовать кнопку, есть уже одна, которая выполняет другую работу.

Я открыт для любых комментариев/помощь доступна, спасибо!

ответ

3

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

Также я бы рекомендовал вам использовать индексы для обеспечения надлежащей привязки к модели. Вам просто нужно использовать IList<ObjInfo> или ObjInfo[] который тривиальным легко достижимо с помощью вызова .ToList() или .ToArray() методы расширения на вашей модели представления, прежде чем передать его мнению:

@using MyApp.Models 
@model IList<ObjInfo> 
... 
@for (var i = 0; i < Model.Count; i++) 
{ 
    <tr> 
     <td> 
      @Html.DisplayFor(x => x[i].OtherObj.m_Name) 
     </td> 
     (...) 
     <td> 
      @Html.CheckBoxFor(x => x[i].m_IsSelected) 
     </td> 
    </tr> 
} 
... 

И теперь ваше действие контроллера может непосредственно принимать список пункты:

[HttpPost] 
public ActionResult SomeAction(IEnumerable<ObjInfo> model) 
{ 
    ... 
} 

и если вы хотите, чтобы найти выбранные значения, вы могли бы просто получить их через LINQ:

[HttpPost] 
public ActionResult SomeAction(IEnumerable<ObjInfo> model) 
{ 
    var selectedItems = model.Where(x => x.m_IsSelected); 
    ... 
} 

Примечание: m_Name и m_IsSelected - катастрофически плохо Соглашение об именах для свойств в C#.


UPDATE:

Еще одна проблема у вас с вашим кодом, что ваш Html.BeginForm не содержит поля ввода. Он имеет только один ActionLink, который, очевидно, только выполняет запрос GET. Если вы хотите, чтобы представить значения, которые вы должны обернуть всю таблицу с формой и использовать кнопку отправки, а не несколько ссылок:

@using MyApp.Models 
@model IList<ObjInfo> 

@{ 
    ViewBag.Title = "Obj Inventory"; 
} 

<h2>Search Inventory</h2> 

<p> 
    @using (Html.BeginForm("SendItems", null, FormMethod.Post)) 
    { 
     (Many search filters which are non-relevant) 

     <table> 
      <tr> 
       <th>Obj Name</th> 
       <th>Number In Stock</th> 
       (...) 
       <th>Select Item</th> 
      </tr> 
     @for (var i = 0; i < Model.Count; i++) 
     { 
      <tr> 
       <td> 
        <!-- 
        This will not be sent to your controller because it's only a label. 
        You will need a corresponding hidden field if you want to get that value back 
        --> 
        @Html.DisplayFor(x => x[i].OtherObj.m_Name) 
       </td> 
       (...) 
       <td> 
        @Html.CheckBoxFor(x => x[i].m_IsSelected) 
       </td> 
      </tr> 
     } 
     </table> 

     <p> 
      Send Items: <button type="submit">Click Here</button> 
     </p> 
    } 
</p> 

Так на самом деле, 2 вещи, которые вы должны знать:

  1. naming convention, что связующее устройство по умолчанию ожидает при привязке к списку
  2. Как использовать инструмент отладки javascript (например, FireBug и/или панель разработчика Chrome), которая позволит вам проверять все значения, которые отправляются на ваш сервер, и сразу признал ли вы соблюдение конвенции, которую вы узнали в 1.
+0

Хорошо, я попробую это. Большое спасибо! Просто вопрос: вы, кажется, предпочитаете использовать «за» вместо «foreach», почему? – hsim

+0

Прочтите эту статью, чтобы понять правильное соглашение об именах, которое вы должны использовать при привязке к списку: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx Как только вы поймете это вы также поймете, почему я использую 'for' вместо' foreach'. –

+1

Wow thats быстро. –

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