如何在MVC中保留复选框列表

西蒙

我正在尝试建立一个HTML帮助器来创建复选框列表,该复选框将使用会话持久保存检查状态。它在大多数情况下都起作用,当您选中和取消选中各个复选框并单击提交时,会记住复选框状态。但是,如果您已选中并提交了复选框,然后返回并清除复选框,然后重新提交(当它们全部清除时)-似乎想记住最后的选择。这是我写的...

[HomeController]

public ActionResult Index()
{
    TestViewModel tvm = new TestViewModel();
    return View(tvm);
}

[HttpPost]
public ActionResult Index(TestViewModel viewModel)
{
    viewModel.SessionCommit();
    return View(viewModel);
}

[索引视图]

@model TestApp.Models.TestViewModel

@{
    ViewBag.Title = "Index";
}

@using (Html.BeginForm())
{
    <p>Checkboxes:</p>
    @Html.CheckedListFor(x => x.SelectedItems, Model.CheckItems, Model.SelectedItems)

    <input type="submit" name="Submit form" />
}

[TestViewModel]

// Simulate the checklist data source
public Dictionary<int, string> CheckItems
{
    get
    {
        return new Dictionary<int, string>()
        {
            {1, "Item 1"},
            {2, "Item 2"},
            {3, "Item 3"},
            {4, "Item 4"}
        };
    }
}

// Holds the checked list selections
public int[] SelectedItems { get; set; }


// Contructor
public TestViewModel()
{
    SelectedItems = GetSessionIntArray("seld", new int[0] );
}


// Save selections to session
public void SessionCommit()
{
    System.Web.HttpContext.Current.Session["seld"] = SelectedItems;
}


// Helper to get an int array from session
int[] GetSessionIntArray(string sessionVar, int[] defaultValue)
{
    if (System.Web.HttpContext.Current.Session == null || System.Web.HttpContext.Current.Session[sessionVar] == null)
        return defaultValue;

    return (int[])System.Web.HttpContext.Current.Session[sessionVar];
}

[HTML帮手]

public static MvcHtmlString CheckedList(this HtmlHelper htmlHelper, string PropertyName, Dictionary<int, string> ListItems, int[] SelectedItemArray)
{
    StringBuilder result = new StringBuilder();
    foreach(var item in ListItems)
    {
        result.Append(@"<label>");
        var builder = new TagBuilder("input");
        builder.Attributes["type"] = "checkbox";
        builder.Attributes["name"] = PropertyName;
        builder.Attributes["id"] = PropertyName;
        builder.Attributes["value"] = item.Key.ToString();
        builder.Attributes["data-val"] = item.Key.ToString();
        if (SelectedItemArray.Contains(item.Key))
            builder.Attributes["checked"] = "checked";

        result.Append(builder.ToString(TagRenderMode.SelfClosing));
        result.AppendLine(string.Format(" {0}</label>", item.Value));
    }
    return MvcHtmlString.Create(result.ToString());
}
public static MvcHtmlString CheckedListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Dictionary<int, string> ListItems, int[] SelectedItemArray)
{
    var name = ExpressionHelper.GetExpressionText(expression);
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    return CheckedList(htmlHelper, name, ListItems, SelectedItemArray);
}

我已经读过这个问题,我认为这可能与模型联编程序不知道何时未选中任何复选框有关,但是即使我已经阅读了该文章以及其他各种帖子,我也无法继续前进。

在一篇文章中,我看到一个隐藏字段通常与复选框结合使用,以传递复选框的“ false”状态,但是我无法使它与将多个复选框发布回单个属性一起使用。

谁能阐明这一点?

编辑:包括本文中突出显示演示项目希望这会帮助某人来帮助我!

用户名

您的主要问题以及取消选中所有项时“记住”先前选择的原因是,您的模型中有一个构造函数,该构造函数调用GetSessionIntArray()获取上次提交表单时存储的值。DefaultModelBinder首先初始化模型(包括调用其默认构造方法),然后设置基于表单值的属性值的作品。在以下情况下

第1步:导航到Index()方法

  • 假设它是第一次调用,并且未添加任何项目Session,则SelectedItemsreturn by的值GetSessionIntArray()int[0],与中的任何值都不匹配CheckItems,因此不会选中任何复选框。

第2步:选中前2个复选框并提交。

  • DefaultModelBinder初始化的新实例TestViewModel,并调用构造函数。SelectedItems再次是的值int[0](尚未添加任何内容Session)。然后读取表单值,SelectedItems现在int[1, 2]的值为(选中的复选框的值)。在返回视图之前,将调用方法中的代码并将int[1, 2]其添加到该代码中Session

步骤3:取消选中所有复选框,然后再次提交。

  • 您的模型再次被初始化,但是这次构造函数从中读取值,Session并且SelectedItemsis的值int[1,2]DefaultModelBinder读取表单值SelectedItems,但有没有(未选中的复选框不提交值),所以没有什么设置和值SelectedItems遗体int[1,2]然后,您返回视图,您的助手将根据以下值检查前两个复选框SelectedItems

您可以通过从模型中删除构造函数并修改扩展方法中的代码以进行测试来解决此问题 null

if (SelectedItemArray != null && SelectedItemArray.Contains(item.Key))
{
    ....

但是,您的实现还有其他问题,包括

  1. id为每个复选框(您使用builder.Attributes["id"] = PropertyName;生成的重复属性都是无效的html。

  2. builder.Attributes["data-val"] = item.Key.ToString();是没有意义的(它产生data-val="1"data-val="1"等)。假设您希望属性用于不打扰的客户端验证,则属性将为data-val="true" data-val-required="The SelectedItems field is required."但是,那么您将需要为错误消息关联一个占位符(由生成,@Html.ValidationMessageFor()并且name每个复选框属性必须是不同的(即,使用索引器-name="[0].SelectedItems"等)。

  3. 您使用属性的值进行绑定,但是正确的方法(所有内置扩展方法都使用该方法)是首先从获取值ModelState,然后从获取值ViewDataDictionary如果没有找到值,最后获取实际模型属性。

  4. var metadata = ModelMetadata.....尽管应该使用,您永远不会使用值(这样您就可以int[] SelectedItemArray从方法中删除最后一个参数(),实际上是在重复的值expression

旁注:在您的情况下,隐藏字段的使用不适用。CheckboxFor()方法生成附加的隐藏输入,因为该方法绑定到bool属性,并确保始终提交值。

我的建议是使用诸如MvcCheckBoxList之类的包(因为我有自己的扩展方法,所以我自己也没有尝试过),至少要等到您花一些时间研究MVC源代码以更好地了解如何创建HtmlHelper扩展方法(对不起)如果听起来很刺耳)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在MVC4中保留复选框选中状态

来自分类Dev

如何在html / php中保留复选框值

来自分类Dev

如何在 React 中保留复选框值类型?

来自分类Dev

如何在自定义复选框视图中保留支持库复选框的样式?

来自分类Dev

如何在R Shiny App的复选框中保留值?

来自分类Dev

搜索后如何在rails中保留复选框的真实值

来自分类Dev

如何在wordpress中保存多个复选框的值

来自分类Dev

如何在recyclerview中保存复选框位置?

来自分类Dev

如何在sqlite中保存android复选框状态?

来自分类Dev

如何在Rails中保存多个复选框值?

来自分类Dev

如何在wordpress中保存多个复选框的值

来自分类Dev

如何在recyclerview中保存复选框位置?

来自分类Dev

如何在Asp.NET MVC中使用复选框创建MultiSelect下拉列表

来自分类Dev

如何在下拉列表MVC视图中添加复选框

来自分类Dev

如何在AngularJS中绑定复选框列表

来自分类Dev

如何在Rails中呈现复选框的数组/列表?

来自分类Dev

如何在复选框列表项之间增加间距?

来自分类Dev

如何使用LocalStorage保留复选框?

来自分类Dev

在带有节点的Angularjs中保存复选框列表

来自分类Dev

如何在Android应用程序中保存复选框状态

来自分类Dev

如何在Android应用程序中保存复选框状态

来自分类Dev

如何在wordpress插件的自定义元框中保存多个复选框值?

来自分类Dev

如何在数据库的不同行中保存多个复选框值

来自分类Dev

搜索后如何在 rails 中保存复选框参数

来自分类Dev

如何创建复选框列表

来自分类Dev

如何处理复选框列表?

来自分类Dev

如何为列表添加复选框

来自分类Dev

如何获取复选框列表的索引

来自分类Dev

返回页面时尝试保留复选框列表的内容

Related 相关文章

热门标签

归档