在ASP.NET MVC应用程序中进行分页时,在Telerik MVC网格中保留CheckBox状态

时间:2011-01-21 16:40:01

标签: asp.net-mvc grid telerik

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

3 个答案:

答案 0 :(得分:11)

如果您正在使用客户端数据绑定,则可以使用下面的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

答案 1 :(得分:0)

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

在分页期间,您只需要重新加载与特定页面相关的记录。您可以使用Linq中的Skip()Take()方法执行此操作。

答案 2 :(得分:0)

使用telerik网格clientemplate在回发和异步回发以及刷新网格和(自动)分页中保留已检查/未检查的复选框状态,我尝试了上面的解决方案但没有用,所以提出了一个更难的解决方案;因为我无法在db中保存状态,所以我使用了会话变量和一个隐藏字段:

首先,一种做ajax回发的方法(参见函数DoAjaxPostAndMore,这里有人提供),其中成功我们处理选择的客户端值,添加和删除为已检查/未选中
我还必须手动检查/取消选中手册ajax帖子中的复选框
第二,隐藏字段(参见'hidSelectedRefs')以保留clientactions,因为我正在使用的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
        }




Then I handled the OnRowDataBound, to ensure the checboxes would be correctly checked on postbacks,


    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>

    

    The telerik mvc Grid is as follows:
    
(you can see I also handled OnDataBinding and OnDataBound, but thats's only to show a "Loading" gif. The controller is named "Output" and the action that normally would be called "Index" here is callled "PrintReferences". The correspondenting Ajax action is called "_PrintReferences") Of interest here is the ClientTemplate for checkbox (cortuesy of someone else herearound, where onclick we call our custom ajax action (named "SelectReferences") on our Output controller via a call to the DoAjaxPostAndMore() javascript/jquery function @(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> that's all for the View. Now, to the controller: //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); }
相关问题