2010-07-20 100 views
8

我有一個名爲「PropertyFeature」的類,它只是包含PropertyFeatureID和Description。這是通過LINQ to SQL映射到SQL Server數據庫表創建的適當模型。一個例子實例/行將是:維護ASP.NET MVC中的複選框動態列表的狀態

PropertyFeatureID: 2 
Description: "Swimming Pool" 

行(PropertyFeatures)當然也可以擴展和收縮,所以我想動態呈現複選框的列表,以便用戶可以選擇其中的任何數量。 我可以動態地呈現複選框很輕鬆了,喜歡的東西:

<%foreach (var Feature in (ViewData["Features"] as IEnumerable<MySolution.Models.PropertyFeature>)) { %> 
<%=Html.CheckBox("Features", new { @id = Feature.PropertyFeatureID, @value = Feature.PropertyFeatureID })%><label for="Feature<%=Feature.PropertyFeatureID%>"><%=Feature.Description%></label> 
<%}%> 

我指定的ID爲每一個複選框,並呈現匹配的標籤,這樣用戶可以直觀地點擊標籤,切換複選框 - 這偉大工程。

我將CheckBox的「名稱」設置爲「Features」,以便所有複選框都以相同的名稱呈現,並且當表單發佈時,MVC Model Binder將它們堆疊到名爲「Features」的單個集合中。這很好地工作。

表單提交後,我使用選中的值並存儲它們,所以我需要實際的整數值,因此我知道選擇了哪個PropertyFeature,而不僅僅是一堆布爾和字段名。所以理想情況下,我希望它是一個易於使用的數組或集合。

當按鈕被點擊時,我能夠從我的Controller方法中檢索選定的值,因爲我已經將參數指定爲int [] Features。

但問題是它不保持狀態。也就是說,當我點擊提交按鈕並重新加載頁面(再次顯示錶單)時,我希望所有動態複選框保留其已檢查的狀態(或不)。我用Html.DropDownListHtml.TextBox創建的所有其他字段都成功保持其狀態,在同一頁的同一頁面上完全沒有問題。

我花了幾個小時閱讀所有關於類似問題的其他線程和文章,有一個談了很多關於使用ICollectionIDictionary捆綁東西,包括每個項目一個布爾值,以便它可以保持複選框州。但是我並不是100%的把握如何在我個人的例子中使用它。我想保持解決方案非常簡單,而不必爲了維持複選框狀態而編寫新類的頁面。

什麼是最乾淨和正確的方法來做到這一點?

+0

問題是,在帖子後重新呈現視圖時。活頁夾查找名爲「功能」的輸入的發佈值。由於這將是一個數組,我想知道這是否只適用於第一個索引?你能測試第一個複選框是否可以維持狀態嗎?如果是這樣的話,你可能不得不考慮更多的涉及列表綁定。 – dotjoe 2010-07-20 16:28:35

+0

是的。其實,我認爲它根本不起作用,即使是第一個複選框。我使用List綁定方法玩了更多,看起來更有希望。但仍然有點複雜,我還沒有能夠鎖定最好的解決方案呢。 – Aaron 2010-07-21 08:15:00

回答

14

我在充分利用各種不同的方法後得到了它的工作。

在視圖:

<%string[] PostFeatures = Request.Form.GetValues("Features");%> 
<% foreach (var Feature in (ViewData["AllPropertyFeatures"] as 
          IEnumerable<MySolution.Models.PropertyFeature>)) 
    { %> 
    <input type="checkbox" name="Features" 
     id="Feature<%=Feature.PropertyFeatureID.ToString()%>" 
     value="<%=Feature.PropertyFeatureID%>" 
     <%if(PostFeatures!=null) 
      { 
      if(PostFeatures.Contains(Feature.PropertyFeatureID.ToString())) 
      { 
       Response.Write("checked=\"checked\""); 
      } 
      } 
     %> /> 
    <label for="Feature<%=Feature.PropertyFeatureID%>"> 
      <%=Feature.Description%></label> <% 
    } %> 

在接收控制器的方法:

public ActionResult SearchResults(int[] Features) 

該方法具有許多優點:

  • 允許標籤是點擊切換通訊ding複選框(可用性)。
  • 允許控制器方法接收一個超整齊的整數數組,它只包含已被選中的整數 - 而不是整個其他一堆未被選中或包含false/null /空白/ 0等的整數。
  • 當包含表單的頁面重新加載時,保留複選框的選中狀態,即保留用戶的選擇。
  • 沒有隨機/雜散類型=從默認的ASP.Net MVC Html.CheckBox助手創建的隱藏輸入字段 - 我知道它有很好的理由,但在這種情況下,我不需要它們,因爲我只想了解哪些ID已被選中,以及這些ID是否位於單個整數int []中。
  • 沒有大量額外的服務器端臃腫的類,助手和其他快樂的混亂需要實現這樣一個簡單的事情。

我會推薦這種方法,任何人想要一個動態複選框列表的最乾淨/無膨脹解決方案,你需要的ID,你只是想開始業務!

0

問題是,當您呈現複選框列表時,您沒有將它們中的任何一個設置爲選中狀態。您需要在ViewData中設置int[] Features,然後在foreach循環中檢查該特徵的ID是否在ViewData中的數組中。

類似:

<%=Html.CheckBox("Features", 
    ((int[])ViewData["SelectedFeatures"]).Contains(Feature.PropertyFeatureID), 
    new { @id = Feature.PropertyFeatureID, @value = Feature.PropertyFeatureID })% 

雖然我沒有測試它,所以它可能不是100%。

+0

謝謝。對不起,要進一步澄清。我不需要最初檢查複選框。它只是在搜索表單上。他們應該始終是空白的,然後用戶只需選擇他們想要搜索的那些。但是,我希望在頁面重新加載時保留所選的那些。 – Aaron 2010-07-21 08:16:56

+0

沒錯。首次加載頁面時,您的SelectedFeatures數組將爲空,因此不會選中複選框。然後在回發中,您將SelectedFeatures數組彈出到ViewData中,並在View加載時使用。 – 2010-07-21 13:40:12

+0

是的。歡呼你的幫助戴夫。 – Aaron 2010-07-22 02:40:23