2009-11-05 74 views
1

我不知所措,因为我一定会漏掉一些东西。刚刚完成ASP.NET MVC 1.0(WROX)和Im试图实现一个视图,执行一个简单的搜索,然后呈现在一个表中的结果。然后,我希望能够通过结果页面。ASP.NET MVC搜索表单与分页

所以我必须从ListingsController搜索行动,需要从的FormCollection一些价值观和对结果进行过滤相应:

 // 
    //POST: /Listings/Search 
    //  /Listings/Page/2 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Search(FormCollection collection,int? page) 
    { 
     var listings = listingRepository.GetListings(); 

     //filter 
     if (collection["TypeOfHouse"] != null) 
     { 
      string[] typeList = collection["TypeOfHouse"].Split(','); 

      foreach (string type in typeList) 
      { 
       listings = from l in listings 
          where l.TypeOfHouse == type 
          select l; 
      } 
     } 

     //display the first page of results 
     int pageSize = 25; 
     var paginatedListings = new PriviledgeV1.Helpers.PaginatedList<Listing>(listings, 0, pageSize); 



     return View("Results", paginatedListings); 
    } 

最初结果视图将与第25条记录被渲染为第1。然后,我有一个结果的行动,处理“分页”:

public ActionResult Results(int? page) 
    { 
     int pageSize = 25; 
     var listings = listingRepository.GetListings(); 
     var paginatedListings = new PriviledgeV1.Helpers.PaginatedList<Listing>(listings, page ?? 0, pageSize); 

     return View(listings); 
    } 

麻烦的是,因为我不再有的FormCollection,我无法正确地过滤结果。因此,如果我尝试使用/ Listings/Results?page = 2从第1页移动到第2页,则结果操作会触发,它将返回所有结果,而不是从搜索操作中筛选的结果集。

我真的很困惑,在这里做什么,至于为什么没有博客/教程解释这一点,这通常标志着我失去了一些东西。

谢谢!

+0

你看jqGrid的?退房:http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx – 2009-11-05 02:45:28

+0

我想保持这个尽可能简单,我可以看到也许使用AJAX调用部分回发。我真的很惊讶他们没有任何地方的这种类型的事情的例子。 – 2009-11-05 02:54:19

回答

5

我想有几种方法可以尝试实现这一点。

  1. 通过查询字符串而不是后传递搜索参数。可以理解的是,对于高级搜索参数,这可能会很复杂和杂乱。
  2. 将POST的结果存储到隐藏的元素。让您的分页控制POST每次都采用相同的操作,而不是单独的Results操作。
  3. 将查询参数存储在会话中保留的对象中。

我确信我们可以从那里获得更多的创意,但那应该给你一个开始。您似乎只关心搜索表单中的一个字段TypeOfListing。你应该可以很容易地通过查询字符串来坚持这一点,所以这将是上面的方法#1。


更新

下面是一些简单的我放在一起,以保持您在客户端搜索。该技术涉及三部分:

  1. 维护页面请求之间的表单。
  2. 用窗体中的隐藏元素管理页面状态。
  3. 让JavaScript拦截您的Paging链接,更新页码隐藏元素并重新提交表单。

下面是所有各个部分的代码。请注意,我使用jQuery,以防您更喜欢别的东西。我欺骗了数据源,只是在实际数据中。另外,我还包括PagedList和PaginationHelper。如果你愿意,可以用你自己的替代品。

\ Controllers \ HomeController。CS(搜索是相关部分):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace MvcApplication2.Controllers 
{ 
    [HandleError] 
    public class HomeController : Controller 
    { 
     List<String> _data; 

     public HomeController() 
     { 
      _data = new List<String>(); 
      _data.Add("Merry"); 
      _data.Add("Metal"); 
      _data.Add("Median"); 
      _data.Add("Medium"); 
      _data.Add("Malfunction"); 
      _data.Add("Mean"); 
      _data.Add("Measure"); 
      _data.Add("Melt"); 
      _data.Add("Merit"); 
      _data.Add("Metaphysical"); 
      _data.Add("Mental"); 
      _data.Add("Menial"); 
      _data.Add("Mend"); 
      _data.Add("Find"); 
     } 

     public ActionResult Search() 
     { 
      Int32 pageNumber, pageSize = 5, total, first; 
      String typeOfListing; 
      PagedList<String> results; 

      if (Request.HttpMethod == "GET") 
      { 
       return View(); 
      } 

      if (!Int32.TryParse(Request.Form["PageNumber"], out pageNumber)) pageNumber = 1; 
      typeOfListing = Request.Form["TypeOfListing"]; 

      first = (pageNumber - 1) * pageSize; 
      total = (from s in _data 
        where s.Contains(typeOfListing) 
        select s).Count(); 
      results = new PagedList<String>(
          (from s in _data 
          where s.Contains(typeOfListing) 
          select s) 
          .Skip(first) 
          .Take(pageSize), 
          total, pageNumber, pageSize); 


       return View(results); 
     } 
    } 
} 

\助手\ PaginationHelper.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Text; 
using System.Web.Routing; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace MvcApplication2.Helpers 
{ 
    public static class PaginationHelper 
    { 
     public static String Pager(this HtmlHelper helper, Int32 pageSize, Int32 pageNumber, Int32 total, String actionName, RouteValueDictionary values) 
     { 
      StringBuilder output = new StringBuilder(); 
      Int32 totalPages = (Int32)Math.Ceiling((Double)total/pageSize); 

      if (values == null) 
       values = helper.ViewContext.RouteData.Values; 

      if (pageNumber > 1) 
       output.Append(CreatePageLink(helper, values, "< Previous ", pageNumber - 1, pageSize)); 

      for (Int32 i = 1; i <= totalPages; i++) 
      { 
       if (i == pageNumber) 
        output.Append(i); 
       else 
        output.AppendFormat(CreatePageLink(helper, values, i.ToString(), i, pageSize)); 

       if (i < totalPages) 
        output.Append(" | "); 
      } 

      if (pageNumber < totalPages) 
       output.Append(CreatePageLink(helper, values, " Next >", pageNumber + 1, pageSize)); 

      return output.ToString(); 
     } 

     private static String CreatePageLink(HtmlHelper helper, RouteValueDictionary values, String text, Int32 pageNumber, Int32 pageSize) 
     { 
      RouteValueDictionary routeDictionary = new RouteValueDictionary(values); 
      routeDictionary.Add("page", pageNumber); 
      routeDictionary.Add("pageSize", pageSize); 

      return helper.ActionLink(text, null, routeDictionary); 
     } 
    } 
} 

\ PagedList.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace MvcApplication2 
{ 
    public class PagedList<T> : List<T> 
    { 
     public Int32 TotalCount { get; protected set; } 
     public Int32 PageNumber { get; protected set; } 
     public Int32 PageSize { get; protected set; } 

     public PagedList(IEnumerable<T> items, Int32 total, Int32 pageNumber, Int32 pageSize) 
      : base(items) 
     { 
      TotalCount = total; 
      PageNumber = pageNumber; 
      PageSize = pageSize; 
     } 
    } 
} 

\浏览\ Home \ Search.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PagedList<String>>" %> 
<%@ Import Namespace="MvcApplication2" %> 
<%@ Import Namespace="MvcApplication2.Helpers" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    Search 
</asp:Content> 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
    <script type="text/javascript"> 
     $(function() { 
      var results = $("#searchResults"); 
      if (results && results.children().length > 2) { 
       $("#searchForm").hide(); 
       $("#searchResults .pager>a").click(submitForm); 
      } 
     }); 

     function submitForm() { 
      var m = this.href.match(/page=(\d+)/i); 
      if (m) { 
       $("#PageNumber").attr("value", m[1]); 
       $("#searchForm").submit(); 
      } 
      return false; 
     } 
    </script> 
    <form id="searchForm" action="<%= Url.Action("Search") %>" method="post"> 
     <input type="hidden" value="1" id="PageNumber" name="PageNumber" /> 
     <fieldset> 
      <legend>Search</legend> 
      <label for="TypeOfListing">Type of Listing</label> 
      <%= Html.TextBox("TypeOfListing", Request.Form["TypeOfListing"]) %> 
      <input type="submit" id="btnSubmit" name="btnSubmit" value="Search" /> 
     </fieldset> 
    </form> 
    <% if (Model != null) 
    { 
    %> 
    <div id="searchResults"> 

     <div class="results-count">Displaying <%=this.Model.Count %> of <%=this.Model.TotalCount %> results. <%=Html.ActionLink("Start a new search", "Search") %>.</div> 
     <% 
       foreach (String result in Model) 
       { 
     %> 
     <div class="result"><%=result %></div> 

     <%  } 
     %> 

     <div class="pager"><%= Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalCount, null, null) %></div> 
    </div> 
    <% 
    } 
    %> 
</asp:Content> 
+0

我想我正在试图锤击的是,有没有另外一种方法来实现这一点。我想要做的就是显示搜索结果和页面直通它们。 作为构建查询,我将不得不传递比TypeOfListing更多。 AJAX会帮助我吗? – 2009-11-05 02:51:35

+0

我想我要走会话路线。有没有人做过这种类型的事情?这似乎是一个非常不恰当的使用Session给我...... – 2009-11-05 14:14:13

+0

AJAX绝对是一个选项,Session并不是那么糟糕(不过这一切取决于你需要做什么),但是你有很多选择。我更新了我的答案,其中包括一个关于如何通过在每个页面中保留原始表单来维护页面搜索的示例。 – HackedByChinese 2009-11-05 17:33:07

0

根本上改变你的形式做一个HTTP GET别人的建议,然后下载PagedList用的NuGet,并使用模型的动作方法绑定到提交按钮,并从PagedList的HTML辅助函数来页码(和使用RouteValuesDictionary设置路由值)。这样,所有东西都会被保存在查询字符串中,而这正是您最想要的搜索页面。 MVC将会对你的ViewModel类进行Coersion。我更喜欢使用ViewModel类而不是一堆参数,因为我认为它更清洁,但只是我的$ .02。

我有一个例子,我博文约here

而且,我继续posted the code on a different thread

+0

如果您只有几个属性,并且您不介意在Action链接中对它们进行硬编码,那么这是一个很好的解决方案。但是,你会如何为几十个和几十个标准做这个。 – 2013-03-07 21:26:16