【问题标题】:Maintain state of a dynamic list of checkboxes in ASP.NET MVC在 ASP.NET MVC 中维护动态复选框列表的状态
【发布时间】:2010-07-20 15:16:45
【问题描述】:

我有一个名为“PropertyFeature”的类,它只包含 PropertyFeatureID 和描述。它是通过 LINQ to SQL 创建的正确模型,映射到 SQL Server 数据库表。一个示例实例/行将是:

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 的“名称”设置为“功能”,因此所有复选框都以相同的名称呈现,当表单发布时,MVC 模型绑定器将它们堆积到一个名为“功能”的集合中。这很好用。

提交表单后,我使用检查的值并存储它们,因此我需要实际的整数值,以便知道选择了哪个 PropertyFeature,而不仅仅是一堆布尔值和字段名称。所以理想情况下,我希望它是一个易于使用的数组或集合。

单击按钮时,我能够从我的控制器方法中检索选定的值,因为我已将参数指定为 int[] Features。

但问题是它不保持状态。也就是说,当我单击提交按钮并重新加载页面(再次显示表单)时,我希望所有动态复选框保持其选中状态(或不保持选中状态)。我用Html.DropDownListHtml.TextBox 创建的所有其他字段都成功地保持了它们的状态,在同一页面上以相同的形式完全没有问题。

我花了好几个小时阅读所有其他类似问题的主题和文章,并且有很多关于使用 ICollectionIDictionary 将事情捆绑在一起并为每个项目包含一个布尔值的讨论,以便它可以保持复选框状态。但我并没有 100% 掌握如何在我个人的例子中使用它。我想保持解决方案非常简单,而不必为了维护我的复选框状态而编写新类的页面。

什么是最干净和正确的方法?

【问题讨论】:

  • 问题是在发布后重新渲染视图时。活页夹查找名为“Features”的输入的发布值。由于这将是一个数组,我想知道这是否仅适用于第一个索引?您可以测试第一个复选框是否可以保持状态?如果是这种情况,您可能需要研究稍微复杂一些的列表绑定。
  • 是的,正确。实际上,我认为它根本不起作用,即使是第一个复选框也是如此。我对 List 绑定方法进行了更多尝试,它似乎更有希望。但还是有点费解,我还没有找到最好的解决方案。

标签: asp.net-mvc binding checkbox viewmodel state


【解决方案1】:

在尝试了各种不同的方法后,我得到了它。

在视图中:

<%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)

这种方法有很多优点:

  • 允许单击标签以切换相应的复选框(可用性)。
  • 允许 Controller 方法接收一个超级整洁的整数数组,其中仅包含已选择的整数 - 而不是其他未选择或包含 false/null/blank/0 等的项目。李>
  • 在包含表单的页面重新加载时保持复选框的选中状态,即保留用户的选择。
  • 没有随机/杂散类型=从默认 ASP.Net MVC Html.CheckBox 帮助程序创建的隐藏输入字段 - 我知道这样做是有充分理由的,但在这种情况下,我不需要它们,因为我只想要了解哪些 ID 已被选中,以及哪些 ID 位于单个、整洁的 int[] 中。
  • 不需要大量额外的服务器端臃肿类、助手和其他令人愉快的混乱来实现这样一个简单的事情。

我会向任何想要动态复选框列表的最干净/无臃肿解决方案的人推荐这种方法,您需要 ID 并且只想开始工作!

【讨论】:

    【解决方案2】:

    问题在于,当您呈现复选框列表时,您并没有将其中任何一个设置为选中状态。您需要在 ViewData 中设置您的 int[] Features,然后在您的 foreach 循环中检查该功能的 ID 是否在 ViewData 的数组中。

    类似:

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

    虽然我没有测试,所以可能不是100%。

    【讨论】:

    • 谢谢。对不起,进一步澄清。我最初不需要检查复选框。它只是在搜索表单上。它们应该始终为空白,然后用户只需选择他们想要搜索的那些。但是我希望在页面重新加载时保留那些选定的内容。
    • 正确。第一次加载页面时,您的 SelectedFeatures 数组将为空,因此不会选中任何复选框。然后在回发时,将 SelectedFeatures 数组弹出到 ViewData 中,它会在 View 加载时使用。
    • 没错。为你的帮助干杯戴夫。
    猜你喜欢
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2016-08-30
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多