【问题标题】:Persist CheckBox State in Telerik MVC Grid While Paging in ASP.NET MVC Application在 ASP.NET MVC 应用程序中分页时保持 Telerik MVC 网格中的复选框状态
【发布时间】:2011-06-13 06:39:15
【问题描述】:

我正在使用 Telerik MVC Grid,其中一列是复选框。如果我选择复选框,然后转到第 2 页,然后返回第 1 页,则所有复选框都消失了。这当然是 HTTP 的工作方式。现在,我将所有选中的复选框放在隐藏字段中,但是由于网格会进行某种回发,所以下次我的隐藏字段会被清除。

【问题讨论】:

  • Telerik:使 MVC 看起来更像 WebForms 的公司。 MVC 是关于删除所有泄漏的 WebForms 抽象层......然后人们开始在它上面使用许多沉重的组件。接下来是某种 ViewState。抱歉,我就是不明白。
  • @rsenna:上次我检查时,Telerik 的专长是 ASP.NET 组件,他们做得很好。他们的 MVC 组件实际上只是使他们的组件与 ASP.NET MVC 一起工作的附加组件。其他地方也有出色的 jQuery 网格,它们运行良好且不需要 ViewState。
  • @Robert Harvey:我只不同意你的第一句话。我是 Telerik WebForms 用户,对我来说,他们的 UltraWebGrid 是维护的噩梦——即使它充满了许多“酷”的功能。其余的显然是正确的。

标签: asp.net-mvc grid telerik


【解决方案1】:

如果您使用客户端数据绑定,您可以使用下面的 javascript/jquery 来维护复选框状态。

维护复选框状态:

var selectedIds = [];

$(document).ready(function () {
    //wire up checkboxes.
    $('#YOUR_GRID_ID :checkbox').live('change', function (e) {
        var $check = $(this);
        console.log($check);
        if ($check.is(':checked')) {
            //add id to selectedIds.
            selectedIds.push($check.val());
        }
        else {
            //remove id from selectedIds.
            selectedIds = $.grep(selectedIds, function (item, index) {
                return item != $check.val();
            });
        }
    });
});

数据绑定后恢复复选框状态:

function onDataBound(e) {
    //restore selected checkboxes.
    $('#YOUR_GRID_ID :checkbox').each(function () {
        //set checked based on if current checkbox's value is in selectedIds.
        $(this).attr('checked', jQuery.inArray($(this).val(), selectedIds) > -1);
    });
}

我的博客上提供了更详细的解释: http://blog.cdeutsch.com/2011/02/preserve-telerik-mvc-grid-checkboxes.html

【讨论】:

    【解决方案2】:

    您需要将复选框的状态保存到数据库中,然后在重新加载页面时再次从数据库中检索它们。

    在分页期间,您只需要重新加载与特定页面相关的记录。您可以使用 Linq 中的 Skip() 和 Take() 方法来做到这一点。

    【讨论】:

    • 我觉得他说的是浏览器Back按钮。
    • 我说的是分页按钮!我无权访问数据库。还有其他地方我可以存储复选框ID的
    【解决方案3】:

    为了在回发和异步回发以及刷新网格和(自动)分页中使用 Telerik 网格客户端模板保留选中/未选中复选框状态,我尝试了上述解决方案但无济于事,因此采用了更难的解决方案;因为我无法将状态保存在数据库中,所以我使用了会话变量和隐藏字段:

    首先,一种进行 ajax 回发的方法(参见函数 DoAjaxPostAndMore ,由附近的人提供),在成功的情况下,我们会处理客户的选择值,添加和删除已选中/未选中
    我还必须手动检查/取消选中手动 ajax 帖子中的复选框
    其次,一个隐藏字段(参见“hidSelectedRefs”)来保留客户端操作,因为我正在使用的 Session 变量在部分渲染中不会出现在客户端

    @model IEnumerable<yourInterfaceOrClass> @{ ViewBag.Title = "Select Something via checkboxes"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Select Something via checkboxes</h2> <!-- we need a form with an id, action must be there but can be an empty string --> <form id="frm" name ="frm" action=""> <p> <!--we need this as Session new values will not be takein in aajax requests clientisde, so it is easier to mange this field, which, in first and subsequent complete postbacks can have the value of the Session variable --> <input type="hidden" name="hidSelectedRefs" id="hidSelectedRefs" value= '@Session["SelectedReferencesToPrint"]' /> </p> <br /> <script type="text/javascript"> //ajax manual post to a custom action of controller, passing the id of record and the state of the checkbox //to adjust the Session value //data: $form.serialize() will have the single checbox value //but only if checked. To make my life eaasier, I added the value (is id ) and the checked/unchecked //state of checkbox (is the $(chkClicked).attr('checked')) function DoAjaxPostAndMore(chkClicked) { var $form = $("#frm"); $.ajax({ type: "POST", url: 'SelectReferences', data: $form.serialize() + '&id=' + $(chkClicked).val() + '&checked=' + $(chkClicked).attr('checked'), error: function (xhr, status, error) { //do something about the error alert("Sorry, we were not able to get your selection..."); }, success: function (response) { //I also needed to check / uncheck manually the checkboxes: $(chkClicked).attr('checked', !$(chkClicked).attr('checked')); //and now put correct values in hidSelectedRefs hidden field: if ($(chkClicked).attr('checked')) { $('input[name=hidSelectedRefs]').val($('input[name=hidSelectedRefs]').val() + '|' + $(chkClicked).val() + '|'); } else { var tmp = $('input[name=hidSelectedRefs]').val(); $('input[name=hidSelectedRefs]').val(tmp.toString().replace('|' + $(chkClicked).val() + '|', '')); } } }); return false; // if it's a link to prevent post } 然后我处理了 OnRowDataBound,以确保在回发时正确检查复选框, function onRowDataBound(e) { var itemsChecked = $('input[name=hidSelectedRefs]').val(); if (itemsChecked) { if (itemsChecked.indexOf('|' + $(e.row).find('input[name=checkedRecords]').val() + '|') >= 0) { $(e.row).find('input[name=checkedRecords]').attr('checked', true); } } } </script> Telerik mvc Grid 如下:
    (你可以看到我也处理了 OnDataBinding 和 OnDataBound,但这只是为了展示一个 “加载”gif。控制器被命名为“Output”,而这里通常称为“Index”的动作被称为“PrintReferences”。对应的 Ajax 动作称为“_PrintReferences”) 这里感兴趣的是复选框的客户端模板(此处其他人的礼貌,其中 onclick 我们通过调用 DoAjaxPostAndMore() javascript/jquery 函数 @(Html.Telerik().Grid<yourInterfaceOrClass>() .Name("Grid") .ClientEvents(e => e.OnDataBinding("showProgress").OnDataBound("hideProgress").OnRowDataBound("onRowDataBound")) .DataBinding(dataBinding => { dataBinding.Server().Select("PrintReferences", "Output", new { ajax = ViewData["ajax"]}); dataBinding.Ajax().Select("_PrintReferences", "Output").Enabled((bool)ViewData["ajax"]); }) .Columns( columns => { columns.Bound(o => o.ID); columns.Bound(o => o.ID) .ClientTemplate( "<input type='checkbox' name='checkedRecords' value='<#= ID #>' onclick='return DoAjaxPostAndMore(this)' />" ) .Width(30) .Title("") .HtmlAttributes(new { style = "text-align:center; padding: 0px; margin: 0px;" }); columns.Bound(o => o.TITLE); columns.Bound(o => o.JOBCODE); columns.Bound(o => o.ORDERCODE ); //columns.Bound(o => o.AUTHOR); columns.Bound(o => o.STATE); columns.Command(commands => commands .Custom("Details") .ButtonType(GridButtonType.Image) .HtmlAttributes(new { @class = "t-icon-details" }) .DataRouteValues(route => route.Add(o => o.ID) .RouteKey("ID")) .Ajax(false) .Action("Details", "Referenza") ); }) .Pageable(paging => paging.PageSize(10) .Style(GridPagerStyles.NextPreviousAndNumeric) .Position(GridPagerPosition.Bottom)) .Sortable() .Filterable() .Resizable(resizing => resizing.Columns(true)) .Reorderable(reorder => reorder.Columns(true)) .NoRecordsTemplate("No Reference found. Please review your filters...") .ColumnContextMenu() ) </form> 这就是视图的全部内容。现在,到控制器: //Get : this is the usally called "Index" action //here we can load data, but we also must ensure the Session variable is fine public ActionResult PrintReferences(bool? ajax, string msgInfo, string selectedRef) { if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } if (string.IsNullOrEmpty(selectedRef)) { selectedRef = "|0|"; } string msgOut = string.Empty; //this is where I get data to show List<yourInterfaceOrClass> ret = LoadData(out msgOut); if (!string.IsNullOrEmpty(msgInfo) && !string.IsNullOrEmpty(msgInfo.Trim())) { msgOut = msgInfo + ' ' + msgOut; } ViewBag.msgOut = msgOut; ViewData["ajax"] = ajax ?? true; return View(ret); } //GridAction: here is telerik grid Ajax get request for your "_Index" [GridAction] public ActionResult _PrintReferences(string msgInfo) { //again, we must take care of Session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } string msgOut = string.Empty; List<yourInterfaceOrClass> ret = LoadData(out msgOut); return View(new GridModel(ret)); } //Post: this is where our custom ajax post goes //we are here if a checkbox is cheched or unchecked //in the FormCollection parameter we get the checkbox value only if checked, and also //(and always) the parms we passed (id of record and state of checkbox: we cannot simply add, //we must also subtract unchecked) [HttpPost] public ActionResult SelectReferences(FormCollection collection) { //we need a session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); //get value passed: id string selectedRefId = collection["id"]; if (!string.IsNullOrEmpty(selectedRefId)) { selectedRefId = "|" + selectedRefId + "|"; } bool cheked = (collection["checked"].ToString()=="checked"); //get vcalue passed :checked or unchecked if (cheked) { //the element is to add wholeSelectionToPrint += selectedRefId; } else { //the element is to remove wholeSelectionToPrint = wholeSelectionToPrint.Replace(selectedRefId, ""); } //set session variable final value Session["SelectedReferencesToPrint"] = wholeSelectionToPrint; return null; } //normal postback: //we will be here if we add a button type submit in our page, //here we can collect all data from session variable to do //something with selection [HttpPost] public ActionResult PrintReferences(FormCollection collection) { //get selected references id if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); wholeSelectionToPrint = wholeSelectionToPrint.Replace("||", "|"); string[] selectdIDs = wholeSelectionToPrint.Split(new char[] { '|' }); foreach (string id in selectdIDs) { if (!string.IsNullOrEmpty(id)) { //do something with single selected record ID System.Diagnostics.Debug.WriteLine(id); } } //omitted [....] ViewData["ajax"] = true; return View(ret); }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      相关资源
      最近更新 更多