0

I've created a WebGrid in an MVC3 web application. In my application sorting,filtering and paging are enabled.

Problem : Whenever a filtering is performed on the webgrid, it populates the filtered data to Webgrid. But if i click on the second page to see the remaining data filtered by Webgrid on my searched text, it doesnot show the remaining filtered data instead it shows complete list of all items in the grid.

How can i get the data in the second page after filtering my data in webgrid.

I've seen a similar question in the site, even it doesnot solved my problem.

My view: I've created a partial view to populate grid, which is called by a normal view. I've followed this tutorial to do that.

Controller: for the first time, Webgrid loads data by using another method in model so as to populate all the data from the database

My Partial View Code:

@{
    ViewBag.Title = "listStudents";
    Layout = "~/Views/Shared/_Layout.cshtml";
    WebGrid grid = new WebGrid(Model, canPage: true, canSort: true, rowsPerPage: 3); 
}

@grid.Pager(WebGridPagerModes.NextPrevious)
        @grid.GetHtml(  //Error at this line
        htmlAttributes: new { id = "grdListStudents" },
    fillEmptyRows: true,
    headerStyle: "tblHeader",
    tableStyle: "tablestyle",
    mode: WebGridPagerModes.All,
    firstText: "<< First",
    previousText: "< Previous", nextText: "Next >",
    lastText: "Last >>",
    columns: new[]{
        grid.Column("intID","SId",canSort:true),
        grid.Column("strFirstName","Name",canSort:true,format:(item)=>item.strFirstName+"   "+item.strLastName),
        grid.Column("strPhone","Phone",canSort:true),
        grid.Column("strEmail","Email",canSort:true),
    }
    )

Here is my code in controller:

public readonly IStudentInfo _istudentrepository;

public studentController( IStudentInfo _iStudentRepository)
{
            this._istudentrepository = _iStudentRepository;
}

//To filter according to Searched Text

[HttpPost]
        public ActionResult studentController(string txtSearch,string ddlTitle,FormCollection collect)
        {
            IEnumerable<Students> sList;
            sList = _istudentlistrepository.getAllStudentsList();

            if (txtSearch != "")
            {
                switch (ddlTitle)
                {
                    case "intId":
                        int sId = Convert.ToInt32(txtSearch);
                        sList = sList.Where(b => b.intId == sId).ToList();
                        break;
                    case "strFirstName":
                        sList = sList.Where(b => b.strFirstName.ToLower().Contains(txtSearch.ToLower())).ToList();
                        break;
                    case "strPhone":
                        sList = sList.Where(b => b.strPhone.ToLower().Contains(txtSearch.ToLower())).ToList();
                        break;
                    case "strEmail":
                        sList = sList.Where(b => b.strEmail.ToLower().Contains(txtSearch.ToLower())).ToList();
                        break;
                }
            }
            return PartialView("_grdListStudents", sList);
        }
    public ActionResult studentController(string sort, string sortdir, int? page)
    {
                int startPage = 0;
                IEnumerable<Students> sList;
                if (page.HasValue && page.Value > 0)
                {
                    startPage = page.Value;
                }
                sList = _istudentrepository.GetList(startPage, PageSize, sort, sortdir);
                return View(sList);

    }

Code in Interface IStudentInfo:

public interface IStudentInfo
    {
        IEnumerable<Students> GetList(int intPage, int intRecords, string strSort, string sortdir);

    }

Code in Model:

private MyEntity _entity;

public StudentListRepository(MyEntity Ent)
{
            this._entity = Ent;
}
public IEnumerable<Students> GetList(int intPage, int intRecords, string strSort, string sortdir)
{

            var finalresult = new Students();
            var bidList = (from userInfo in _entity.tbl_UserInf
                           join user in _entity.tbl_User on userInfo.UserId equals user.UserId
                           select new Students()
                           {
               intID=user.UserId,
                               strFirstName = user.FirstName,
                               strEmail = userInfo.EmailId,
                               intPhone=userInfo.Phone
                           }).OrderByDescending(m => m.intID);
            finalresult.TotalResult = bidList.Count();
            switch (strSort)
            {
                case "intID":
                    if (sortdir == "ASC")
                    {
                        sList = sList.OrderBy(r => r.Id);
                    }
                    else
                    {
                        sList= sList.OrderByDescending(r => r.Id);
                    }
                    break;
    case "strFirstName":
                    if (sortdir == "ASC")
                    {
                        sList = sList.OrderBy(r => r.strFirstName);
                    }
                    else
                    {
                        sList= sList.OrderByDescending(r => r.strFirstName);
                    }
                    break;
    case "strEmail":
                    if (sortdir == "ASC")
                    {
                        sList = sList.OrderBy(r => r.strEmail);
                    }
                    else
                    {
                        sList= sList.OrderByDescending(r => r.strEmail);
                    }
                    break;
                    //repeat same for phone
           }
          finalresult.lstStudents = sList.Skip(intPage * intRecords).Take(intRecords).ToList();
           return sList.ToArray();
}
Community
  • 1
  • 1
Karthik Chintala
  • 5,465
  • 5
  • 30
  • 60

1 Answers1

0

Your viewmodel should contain the list of items and the values for searchtext, pagesize, current page and total record count. I use a generic base class with these properties:

public class PagedViewModel<T> {
    public IList<T> Items { get; set; }
    public int PageSize { get; set; }
    public int RowCount { get; set; }
    public int Page { get; set; }
    public int PageCount { get; set; }
    public string sort { get; set; }
    public string sortdir { get; set; }
}

Then your concrete Viewmodel looks just like this:

public class StudentsListViewModel : PagedViewModel<Students> {
    public string Search { get; set; }
}

From your comments i read, you want to Ajax.BeginForm to update your grid via ajax. Then you need two actions: One for the whole page and one for the grid (partial).

The first action returns the whole page:

public ActionResult Index() {
    StudentsListViewModel model = queryStudents(1, 10, null);
    return View(model);
}

The second action returns the partial view for the grid:

public ActionResult UpdateStudentsGrid(StudentsListViewModel model) {
    model.Items = queryStudents(model);
    return Partial("StudentsGrid", model);
}

A helper method queries the data and returns the filtered list:

private StudentsListViewModel queryStudents(int page, int rowsPerPage, 
                                             string search) {
    StudentsListViewModel = new StudentsListViewModel {
        Page = page,
        PageSize = rowsPerPage,
        Items = db.Students.Where(s => s.Name == search || search == null)
            ... add paging...;
    };
    // ToDo: set additional properties on model
    return model;
}

The main page view contains your ajax form. The list will be rendered by the partial view:

@model StudentsViewModel
@using (Ajax.BeginForm("UpdateStudentsGrid", 
         new AjaxOptions { UpdateTargetId = "grid" })) {

    @Html.TextboxFor(m => m.Search)
    <input type=submit" />
    <div id="grid">
        @Html.Partial("StudentsGrid", Model);
    </div>
}

The partial view looks something like this and renders just the grid:

@{ 
    var grid = new WebGrid(Model.Items, canPage: true, canSort: true,
                           rowsPerPage: Model.PageSize);
}
@grid.GetHtml(...)

I havn't tested or compiled the code: it will probably not work as it stands here but it should get you started.

EDIT: The forgotten pager

For getting the pager links to work with your form, you can simple change the form method from POST to GET according to this article: http://www.mikepope.com/blog/DisplayBlog.aspx?permalink=2377

But i'm not sure how that works with an ajax form.

Another approach would be to intercept the clicks on the pager links and submit the form with method POST instead: http://forums.asp.net/t/1703486.aspx/1

Jan
  • 15,802
  • 5
  • 35
  • 59
  • Thank you, but still i have issue. I wrote the actionresult as you posted. It sorts the columns for the first time but if i hit `page 2`, `txtSearch` is becoming empty. How to resolve it – Karthik Chintala Nov 27 '12 at 05:42
  • I have sorting,paging in one controller with `[HttpGet]` and filtering with other controller with `[HttpPost]`. How do i merge both ?. Im using Ajax.BeginForm for search controls. If i give FormMethod.Get in Ajax.BeginForm it is not giving any grid – Karthik Chintala Nov 27 '12 at 05:53
  • when i click on `page 2` it is going to `[HttpGet]` method rather than `[HttpPost]`. Even i tried to use @AjaxBeginForm("","",FormMethod.Post,new AjaxOptions { UpdateTargetId = "grid" }) but it didnot work for me – Karthik Chintala Nov 27 '12 at 11:23
  • Ah ok, i have forgotten the pager :) I found an article about that topc. See my edits – Jan Nov 27 '12 at 11:35
  • Even Mike's answer using JQuery couldnot help me. I've tried `$(function () { $('th a, tfoot a').click(function () { $('form').attr('action', $(this).attr('href')).submit(); return false; });` – Karthik Chintala Nov 27 '12 at 12:04
  • You have to adapt it to your view. – Jan Nov 27 '12 at 12:10
  • I mean you have at least to adapt the selectors, ids, etc. in the jquery code – Jan Nov 27 '12 at 12:18
  • The script is defined with all the predefined tags. so, i think there is no need to add additional ids @Jan – Karthik Chintala Nov 27 '12 at 12:24
  • Its only just a View that is remaining @Jan. My View is same as you have posted here. ok, let me post that too – Karthik Chintala Nov 27 '12 at 12:44