自动 Post 复选框点击后退页

Auto Post Back Page On CheckBox Onclick

这一定很简单,但我已经研究了几天如何通过单击复选框来更改行值。我想要的是更改单击 CheckBox 的列的值,并在 CheckBox 为真时保持选中状态。否则,如果为假,它将保持未选中状态。下面是一个屏幕截图,当一行的 Public Post 列值为 'No' 时,CheckBox 将保持未选中状态。当我检查 CheckBox 时,反之亦然意味着它将保持选中状态并且值将为“Yes”。

我不确定该怎么做,看到了一些处理这种情况的问题或链接:

ASP.NET MVC submitting form on checkbox click

How can I get CheckBox to maintain checked state across postback in ASP.NET MVC?

但我想有一些更高级的想法来实现它,因为它与 ASP.NET Web Form 完全不同。如果专家分享一些想法或有助于理解的有用链接,我将不胜感激。谢谢。

顺便说一句,以下是我正在使用的class。我不确定如何处理来自控制器的回发,到目前为止,以下是使用 Ajax 完成的。但它不工作或更新:

型号:

public class Product
{
    [Key]
    public int Id { get; set; }
    [Required(ErrorMessage = "Details can't be blank")]
    [DataType(DataType.Text)]
    public string Name{ get; set; }
    public string Date_Posted { get; set; }
    public string Time_Posted { get; set; }
    public string Time_Edited { get; set; }
    public string Date_Edited { get; set; }
    public string Public { get; set; }
    public double Price { get; set; }
    public int User_Id { get; set; }
    public bool Status { get; set; } //This is bit column that I am trying to change and not sure how to handle this from controller
    public List<Product> allLists;
    public IEnumerable<Product> Items;
    public Pager Pager;
}

控制器 - HomeController.cs:

    [HttpPost]
    public ActionResult CheckValue(int id)
    {
        MainDbContext db = new MainDbContext();
        List result = db.Product.Find(id);

        if (ModelState.IsValid)
        {
            result.Public = "Yes";
            result.Status = true;

            db.Entry(result).State = EntityState.Modified;
            db.SaveChanges();
        }

        return View(db.Lists.ToList());
    }

查看 - Home/Index:

@model OurFirstWebApp.Models.Product
@{
    ViewBag.Title = "Index";
    var username = User.Identity.Name;
}

<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script language="javascript">
$(function () {
    $('.toggle').change(function () {
        //alert("Hello");
        var self = $(this);
        var url = self.data('url');
        var id = self.attr('id');
        //var value = self.prop('checked');

        $.ajax({
            url: url,
            data: { id: id },
            type: 'POST',
            success: function (response) {
                alert(response);
                $("#divData").load(window.location + " #divData");
            }
        });
    });
});

<div id="divData">
<table class="table table-bordered table-condensed" id="data">
    <thead>
        <tr>
            <th style="text-align:center;">ID</th>
            <th style="text-align:center;">Products</th>
            <th style="text-align:center;">Time Posted</th>
            <th style="text-align:center;">Time Edited</th>
            @if (@User.Identity.IsAuthenticated)
            {
                <th style="text-align:center;">Status</th>
                <th style="text-align:center;">Edit</th>
                <th style="text-align:center;">Delete</th>
                <th style="text-align:center;">Public Post</th>
            }
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Items)
        {
            <tr>
                <td id="ID" style="text-align: center;">@Html.DisplayFor(modelItem => item.Id)</td>
                <td style="text-align: center;">@Html.DisplayFor(modelItem => item.Name)</td>
                <td style="text-align: center;">@Html.DisplayFor(modelItem => item.Time_Posted)</td>
                <td style="text-align: center;">@Html.DisplayFor(modelItem => item.Time_Edited)</td>

                @if (@User.Identity.IsAuthenticated)
                {
                    <td style="text-align: center;">@Html.CheckBoxFor(modelItem => item.Status, new { id = item.Id, @class = "toggle", data_url = Url.Action("CheckValue", "Home") })</td>
                    <td style="text-align: center;"><a href="@Url.Action("Edit", "Auth")/@Html.DisplayFor(modelItem => item.Id)">Edit</a></td>
                    <td style="text-align: center;"><a href="@Url.Action("Delete", "Auth")/@Html.DisplayFor(modelItem => item.Id)">Delete</a></td>
                    <td id="chngData" style="text-align: center;">@Html.DisplayFor(modelItem => item.Public)</td>

                }
            </tr>
        }
   </tbody>
</table>

您的属性 bool Statusstring Public 令人困惑,并且在数据库中有 2 个字段表示相同的东西是个坏主意。你应该有一个 属性(比如)

public bool IsPublicPost { get; set; }

单独的复选框应该足以表示值,但如果您确实想要额外的列,则在视图模型中添加一个额外的 属性(例如)

public string PublicPostDisplayText
{
    get { return IsPublicPost ? "Yes" : "No"; }
}

或更好,为输出 "Yes" 或 "No".

的属性创建一个 DisplayTemplate

接下来,您无法使用 foreach 循环正确绑定到集合模型(有关详细信息,请参阅 ),您需要使用 for 循环或自定义 EditorTemplate 对于 typeof Product

for(int i = 0; i < Model.Items.Count; i++)
{
    <tr>
        <td>@Html.DisplayFor(m => m.Items[i].Id)</td> // see notes below
        ....
        <td>@Html.CheckBoxFor(m => m.Items[i].IsPublicPost, new { @class = "post-checkbox", data_id = Model.Items[i].Id })</td>
        // If you really want the extra column
        <td class="post-text">@Html.DisplayFor(m => m.Items[i].PublicPostDisplayText)</td>
    </tr>
}

那么更新数据库的脚本就是

var url = '@Url.Action("UpdatePublicPostStatus", "Home")';
$('.post-checkbox').click(function() {
    var isChecked = $(this).is(':checked');
    var id = $(this).data('id');
    var row = $(this).closest('tr'); // only if you display the extra column
    $.post(url, { id: id, isPublicPost: isChecked }, function(response) {
        if (response) {
            // no need to do anything, but if you display the extra column
            var displayText = isChecked ? 'Yes' : 'No';
            row.find('.post-text').text(displayText);
        } else {
            // Oops something went wrong - reset the checkbox and display error?
        }
    }).fail(function() {
        // Oops something went wrong - reset the checkbox and display error?
    });
});

最后是控制器方法

[HttpPost]
public JsonResult UpdatePublicPostStatus(int id, bool isPublicPost)
{
    MainDbContext db = new MainDbContext();
    var product = db.Product.Find(id);
    if (product != null) // always check
    {
        product.IsPublicPost = isPublicPost;
        db.Entry(product).State = EntityState.Modified;
        db.SaveChanges();
        return Json(true);
    }
    // If something went wrong, e.g. an exception, then return Json(null);
}

旁注。

  1. 重复的id属性无效html(不要在里面添加then 循环,除非它们是唯一的)
  2. 使用样式表而不是内联样式,例如td:nth-child(1) { text-align:center; }
  3. 使用 if (ModelState.IsValid) 毫无意义(而且总是 return true) 在你的情况下,因为你没有发布和绑定到 模型.