10

我正在尝试学习 Asp.net mvc。我知道它与形式不同,我可能需要改变我的思维方式。我的问题是关于 webgrid 。当我将 webgrid 添加到我的页面并使用 Post 点击搜索按钮时,它会使用寻呼机等呈现表格。但是寻呼机上的链接没有发布表单,它们只是链接,我丢失了所有表单的数据。

控制器有两种索引方法,一种用于获取,另一种用于发布。为了让我什么都不做,我只是在这种情况下创建新的视图模型搜索类并将其设置为视图。对于我的发布方法,我抓住我的视图模型进行搜索并将填充的视图模型设置为查看。

问题:webgrid 将寻呼机呈现为链接,因此它将进入索引以获取但由于它不是发布请求,因此我没有填写任何表单字段,并且我的搜索不会提供完全相同的结果集。

也许示例代码可以更好地解释它。

看法:

<form action="" method="post">

Esas no : @Html.TextBoxFor(x=>x.Name)
Yil : @Html.TextBoxFor(x=>x.Year)

<input type="submit" value="Search" />

<hr />
@ViewBag.Message
<hr />

@{ var grid = new WebGrid(Model.Results,rowsPerPage:5);}

@grid.GetHtml(tableStyle:"table",htmlAttributes:new {id="tbl"} )

</form>

这是我的控制器:搜索发生在 Index Post 方法中,它只有我的 viewmodel 类。

    private ISearchContext _sc;

    public  MyController(ISearchContext sc)
    {
        _dc = dc;
    }

    //
    // GET: /Dava/

    public ActionResult Index()
    {
        var search = new Search();
        ViewBag.Message = "";
        return View(search);
    }

    [HttpPost]
    public ActionResult Index(Search search)
    {

        Search sres = _dc.SearchFromRepository(search);
        ViewBag.Message = String.Format("Count:{0} ",sres.Results.Count);
        return View(sres);
    }

搜索模型类是这样的:

public class Search
{
    public int Year { get; set; }
    public string Name { get; set; }


    public IList<Item> Results { get; set; }

    public Search()
    {
        Results = new List<Item>();
    }
}
4

4 回答 4

9

解决此问题的一种方法是使用 javascript 并订阅任何寻呼机链接的单击事件,然后获取所需页面的值,将其注入表单上的隐藏字段并将表单提交到服务器,以便其他两个值也被发送。

因此,首先Page在视图模型上添加一个可为空的整数属性,Search并将相应的隐藏字段添加到包含所选页码的表单中:

@Html.HiddenFor(x => x.Page, new { id = "page" })

然后,您只需要在页面中添加一个小的 javascript 片段即可订阅寻呼机链接的 .click 事件:

$(function () {
    $('tfoot a').click(function () {
        // when the user clicks on any of the pager links
        // try to extract the page number from the link and
        // set the value of the hidden field
        var page = this.href.match(/page=([0-9])+/)[1];
        $('#page').val(page);

        // submit the form so that the POST action is invoked
        // passing along the search criteria (Name and Year) along
        // with the page hidden field value to the Index action
        $('form').submit();

        // cancel the default action of the link which is to simply redirect
        // to the Index action using a GET verb.
        return false;
    });
});
于 2011-06-14T13:30:42.317 回答
5

这是一个不使用 JavaScript 的解决方法。

我看到的问题是,分页链接没有收到任何必须保留的路由信息​​,例如搜索过滤器。IMO这是一个公然的疏忽!在这里多加一点想法会省去很多头痛!

这种技术“抛弃”了 WebGrid 的内置分页,并使用 Helper 生成分页链接以及我们想要的宝贵路由数据。

完成后,您只需将 WebGrid 呈现为仅网格,并使用 Helper 制作分页链接。这里的一个优势是您可以将它们放在顶部和底部,这是我们喜欢做的。

我尝试使用与 NuGet 放入您的解决方案的 Pager.css 中提供的类似的 CSS。对于你们中的一些人来说,帮助器应该足够完整,但它很容易扩展。

新 新 新我刚刚用 Ajax 版本更新了助手。我对 Razor 助手有点不满意,所以我不知道如何重新分解它以使用通用模板;请问有人吗?重要的额外细节是传递AjaxOptions并确保POST用作动词,否则您可能无法使用正确的控制器方法。

助手(App_Code/LocalHelpers.cshtml):

@helper DoPager(System.Web.Mvc.HtmlHelper hh, string pageActionName, WebGrid grid, int maxPageLinks, object rvd) {
<div class="pager">
<div class="pageof">Page <b>@(grid.PageIndex + 1)</b> of <b>@grid.PageCount</b></div>
@if (grid.PageCount > 1) {
<ul>
<li>
@{ RouteValueDictionary rvdp1 = new RouteValueDictionary(rvd);
   rvdp1.Add("Page", 1);
}
@hh.ActionLink("<<", pageActionName, rvdp1)
</li>
@{ int start = Math.Max(0, grid.PageIndex - maxPageLinks / 2); }
@for (int ix = 0; ix + start < grid.PageCount; ix++) {
    int pageno = start + ix + 1;
    var css = hh.Raw(pageno - 1 == grid.PageIndex ? " class=\"highlighted\"" : "");
    RouteValueDictionary rvdp = new RouteValueDictionary(rvd);
    rvdp.Add("Page", pageno);
<li@css>
@hh.ActionLink(pageno.ToString(), pageActionName, rvdp)
</li>
    if (ix >= maxPageLinks) { break; }
}
<li>
@{ RouteValueDictionary rvdpX = new RouteValueDictionary(rvd);
   rvdpX.Add("Page", grid.PageCount);
}
@hh.ActionLink(">>", pageActionName, rvdpX)
</li>
</ul>
}
</div>
}
@helper DoAjaxPager(System.Web.Mvc.AjaxHelper aa, System.Web.Mvc.Ajax.AjaxOptions aopts, System.Web.Mvc.HtmlHelper hh, string pageActionName, WebGrid grid, int maxPageLinks, object rvd) {
<div class="pager">
<div class="pageof">Page <b>@(grid.PageIndex + 1)</b> of <b>@grid.PageCount</b></div>
@if (grid.PageCount > 1) {
<ul>
<li>
@{ RouteValueDictionary rvdp1 = new RouteValueDictionary(rvd);
   rvdp1.Add("Page", 1);
}
@aa.ActionLink("<<", pageActionName, rvdp1, aopts)
</li>
@{ int start = Math.Max(0, grid.PageIndex - maxPageLinks / 2); }
@for (int ix = 0; ix + start < grid.PageCount; ix++) {
    int pageno = start + ix + 1;
    var css = hh.Raw(pageno - 1 == grid.PageIndex ? " class=\"highlighted\"" : "");
    RouteValueDictionary rvdp = new RouteValueDictionary(rvd);
    rvdp.Add("Page", pageno);
<li@css>
@aa.ActionLink(pageno.ToString(), pageActionName, rvdp, aopts)
</li>
    if (ix >= maxPageLinks) { break; }
}
<li>
@{ RouteValueDictionary rvdpX = new RouteValueDictionary(rvd);
   rvdpX.Add("Page", grid.PageCount);
}
@aa.ActionLink(">>", pageActionName, rvdpX, aopts)
</li>
</ul>
}
</div>
}

看法:

<center>
@LocalHelpers.DoPager(Html, "Index", grid, 10, new { CurrentFilter = ViewBag.CurrentFilter })
</center>
@grid.Table(
    tableStyle: "centerit",
    columns: grid.Columns(
        grid.Column(format: @<span>@Html.ActionLink("Edit", "Edit", new { id = item.ID }) | @Html.ActionLink("Details", "Details", new { id = item.ID }) | @Html.ActionLink("Delete", "Delete", new { id = item.ID })</span>),
            grid.Column("PartNumber", "Part Number"),
            grid.Column("Description", "Description"),
            grid.Column("Regex", "Regex")
            )
        )
<center>
@LocalHelpers.DoPager(Html, "Index", grid, 10, new { CurrentFilter = ViewBag.CurrentFilter })
</center>

在我看来,我正在回收“CurrentFilter”以了解要过滤的内容。这连接到控制器动作(未图示)。

于 2011-08-12T15:37:50.070 回答
3

行。我有一个使用 AJAX 和部分视图的更优雅的解决方案,应该一劳永逸地解决这个问题

这是我的模型:

public class SearchResultModel
{
        public string SearchText{ get; set; }
        public List<YourObject> Results { get; set; }
        public int TotalResults { get; set; }
}

搜索视图的结构如下:

@model SearchResultModel
@using (Ajax.BeginForm("SearchAction", "SearchController", new AjaxOptions{UpdateTargetId = "data-grid", HttpMethod="Post"}))
{
        @Html.TextBoxFor(m => m.SearchText)
        <input class="myButton" type="submit" value="Search" />
}
<br />
<div id="data-grid">
       @Html.Partial("SearchResults", new SearchResultModel())
</div>

SearchResults 部分视图是:

@model SearchResultModel
@{
    if (Model.Results != null && Model.Results.Count > 0)
    {
            var grid = new WebGrid(canPage: true, rowsPerPage: 10, canSort: true, ajaxUpdateContainerId: "grid");
            grid.Bind(Model.Results, rowCount: Model.TotalResults, autoSortAndPage: false);
            grid.Pager(WebGridPagerModes.All);

            @grid.GetHtml(htmlAttributes: new { id = "grid" },
            columns: grid.Columns(
                grid.Column("YourColumn1"),
                grid.Column("YourColumn2"),
                grid.Column("YourColumn3")
            ),
            tableStyle: "datatable",
                rowStyle: "datatable-normal",
                    alternatingRowStyle: "datatable-alt"
            );
    }
    else
    {
    <span>No Results</span>
    }
}

最后,控制器是:

public class SearchController
{
        public ActionResult SearchAction(SearchResultModel model)
        {
            return RedirectToAction("SearchResults", new { id = model.SearchText });
        }

        public ActionResult SearchResults(string id)
        {
            string searchText = id;
            int page = 1;
            if(Request["page"] != null)
                int.TryParse(Request["page"], out page);

            SearchResultModel model = new SearchResultModel();
            //Populate model according to search text and page number
            //........
            //........
            return PartialView(model);
        }
}

希望这将有助于节省一些时间和焦虑!

于 2012-06-11T19:49:38.193 回答
0

我的回答包括让您在 Session 上进行搜索,仅此而已。该解决方案很好,因为您可以使其适应您的实际情况,并且不需要特定的类或 JQuery。

魔术发生在您的 Index ActionResult(或您的默认 ActionResult,它将以其默认行为呈现网格页面)中。

代码示例:

    [HttpGet]
    public ActionResult Index()//My default action result that will render the grid at its default situation
    {
        SearchViewModel model = new SearchViewModel(); 

        if (Request.IsAjaxRequest()) //First trick is here, this verification will tell you that someone sorted or paged the grid.
        {
            if (Session["SearchViewModel"] != null) //If session is not empty, you will get the last filtred values from it.
                model = (SearchViewModel)Session["SearchViewModel"];
        }
        else // If it is not an AjaxRequest, you have to clear your Session, so new requests to Index with default behavior won't display filtred values.
        {
            Session["SearchViewModel"] = null;
        }

        model.GridResult = ExecuteFilter(model); // OPITIONAL! This code dependes on how is your real world situation. Just remember that you need to return a default behavior grid if the request was not called by the WebGrid, or return filtred results if WebGrid requested.
        return View(model);
    }

因此,这将是您的默认 ActionResult。它将验证请求是否被 WebGrid 分页或排序事件调用,以决定是否返回过滤结果或正常行为结果。

下一步是搜索 POST ActionResult:

    [HttpPost]
    public ActionResult Index(SearchViewModel pesquisa) // IMPORTANT!! It is necessary to be the SAME NAME of your GET ActionResult. The reason for that I know, but won't discuss here because it goes out of the question.
    {
        SearchViewModel model = new SearchViewModel();
        model.GridResult = ExecuteFilter(pesquisa); // Execute your filter
        Session["SearchViewModel"] = model; //Save your filter parameters on Session.
        return View("Index", model);
    }

就是这样。Index.cshtml 没有任何技巧。只是 ActionResult 索引的 SearchForm,将我的 SearchViewModel 作为参数传递。

为什么这个解决方案有效?

好吧,当您单击排序或分页时,WebGrid 会执行类似于此的 JavaScript:

$('#yourGrid').load('it pass the url used to display your current Page, and some paging or sorting parameters, but those are used by the WebGrid')

由于它使用 .load() 方法,因此请求将是一个 GET,并且会命中您的 Index GET ActionResult。但这是一个 AJAX 调用,所以我们的魔术将使用您保存在 Session 上的参数再次执行过滤器。

我提醒的唯一细节是关于您的默认网格行为。GET Index ActionResult 必须永远返回一个有效的网格结果,不管它是否在 Session 上有过滤器。

于 2013-03-20T15:18:26.167 回答