我正在构建一个MVC-App,我正在寻找一种在我的视图中进行分页的有效方法。
到目前为止,我已经安装了following分页系统。但是,如果此分页系统运行良好,则存在缺陷:视图中显示的列表不是完整列表,而是用户根据页码查看的列表的哪个部分。缺点是如果我使用jQuery系统对项目进行排序,它只会对当前页面中的项目进行排序,而不是对总列表进行排序。
请允许我证明我的意思。说我有这个观点:
@using MyApp.Models
@model PagedList.IPagedList<MyApp.Utilities.CardDisplay>
<h2>
Cards Display Results
</h2>
<script type="text/javascript">
$(document).ready(function(){
$('#cardRarity').change(function () {
var showCardRarity = $(this).val();
if (showCardRarity == "All") {
$(".cardRarity").show();
} else {
$(".cardRarity").hide();
$(".cardRarity-" + showCardRarity).each(function() {
$(this).show();
});
}
});
$('#cardType').change(function() {
var showCardType = $(this).val();
if (showCardType == "All") {
$(".cardType").show();
} else {
$(".cardType").hide();
$(".cardType-" + showCardType).each(function() {
$(this).show();
});
}
});
$('#cardColor').change(function() {
var showCardColor = $(this).val();
if (showCardColor == "All") {
$(".cardColor").show();
} else {
$(".cardColor").hide();
$(".cardColor-" + showCardColor).each(function() {
$(this).show();
});
}
});
});
</script>
@using (Html.BeginForm())
{
<p>Filter by rarity: <select name="cardRarity" id="cardRarity" tabindex="1">
<option value="All">All</option>
<option value="Land">Land</option>
<option value="Common">Common</option>
<option value="Uncommon">Uncommon</option>
<option value="Rare">Rare</option>
<option value="Mythic Rare">Mythic Rare</option>
<option value="Special">Special</option>
</select>
Filter by type: <select name="cardType" id="cardType" tabindex="2">
<option value="All">All</option>
<option value="Artifact">Artifact</option>
<option value="Instant">Instant</option>
<option value="Creature">Creature</option>
<option value="Land">Land</option>
<option value="Planeswalker">Planeswalker</option>
<option value="Enchantment">Enchantment</option>
<option value="Sorcery">Sorcery</option>
<option value="Tribal">Tribal</option>
</select>
Filter by color: <select name="cardColor" id="cardColor" tabindex="3">
<option value="All">All</option>
<option value="White">White</option>
<option value="Red">Red</option>
<option value="Blue">Blue</option>
<option value="Green">Green</option>
<option value="Black">Black</option>
<option value="Gold">Gold</option>
<option value="Colorless">Colorless</option>
</select>
</p>
}
@if (Model.Count > 0)
{
if (Model.PageCount > 1)
{
<div class="center">
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "DisplayCardsResults", new { _page = 1, _sortOrder = ViewBag._currentSort })
@Html.Raw(" ")
@Html.ActionLink("< Prev", "DisplayCardsResults", new { _page = Model.PageNumber - 1, _sortOrder = ViewBag._currentSort })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "DisplayCardsResults", new { _page = Model.PageNumber + 1, _sortOrder = ViewBag._currentSort })
@Html.Raw(" ")
@Html.ActionLink(">>", "DisplayCardsResults", new { _page = Model.PageCount, _sortOrder = ViewBag._currentSort })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>
}
<table id="resultTable">
<tr>
<th>Item number</th>
<th>Card Name</th>
<th>Number</th>
<th>Color</th>
<th>Mana Cost</th>
<th>Mana Converted</th>
<th>Card Type</th>
<th>Power</th>
<th>Toughness</th>
<th>Rarity</th>
<th>Card Set</th>
<th>Artist Name </th>
<th>Actions </th>
</tr>
@for (int i = 0; i < Model.Count; i++)
{
var className = i % 2 == 0 ? "even" : "odd";
var row = ((i + 1) + ((Model.PageNumber - 1) * 50));
<tr class="@className cardRarity cardRarity-@(Model[i].mCardRarity.Replace(" ", "-"))
cardType cardType-@(Model[i].mStrippedCardType)
cardColor cardColor-@(Model[i].mCardColor)">
<td>@row</td>
<td class="center">
@(Model[i].mCardFlagFace == CardInfo.FlagFaceValue.Normal ?
Html.ActionLink(Model[i].mCardName, "CardDetails", new {_cardId = Model[i].mCardID}) :
Html.ActionLink(Model[i].mCardName + " // " + Model[i].mChildCard.mCardName, "CardDetails", new {_cardId = Model[i].mCardID}))
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardNumber)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardColor)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardManaCost)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardManaConverted)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardType)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardPower)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardToughness)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardRarity)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardSet.mCardSetName)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardArtistName)
</td>
<td>
@Html.ActionLink("Details", "Details", new {@_cardId = Model[i].mCardID})
@Html.ActionLink("Edit", "Edit", new {@_cardId = Model[i].mCardID})
@Html.ActionLink("Delete", "Delete", new {@_cardId = Model[i].mCardID})
</td>
</tr>
}
</table>
if (Model.PageCount > 1)
{
<div class="center">
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "DisplayCardsResults", new { _page = 1, _sortOrder = ViewBag._currentSort })
@Html.Raw(" ")
@Html.ActionLink("< Prev", "DisplayCardsResults", new { _page = Model.PageNumber - 1, _sortOrder = ViewBag._currentSort })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "DisplayCardsResults", new { _page = Model.PageNumber + 1, _sortOrder = ViewBag._currentSort })
@Html.Raw(" ")
@Html.ActionLink(">>", "DisplayCardsResults", new { _page = Model.PageCount, _sortOrder = ViewBag._currentSort })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>
}
}
假设我有50张要显示的卡片列表,但允许的卡片页数为20.根据此视图,如果我将所选选项Card Type
更改为Creature
,则视图确实会对所有生物进行排序和显示,但仅针对显示的20张卡而不是整个列表。
这就是我需要帮助的原因:我需要想办法将整个列表加载到视图中,然后整理出一些分页方式,或者只重新显示想要的项目,我很想做它不必重写我的控制器方法,但我不介意添加新功能。我听说JSon可能有所帮助,但我不知道它是如何工作的。任何人都可以帮助我吗?
修改
这是工作代码!
首先,我修改了这样的javascript函数:
<script type="text/javascript">
$(document).ready(function () {
$('#cardRarity').change(function () {
var showCardRarity = $(this).val();
refreshResults(($(this).attr("id")), showCardRarity);
});
$('#cardType').change(function () {
alert("Type changed");
var showCardType = $(this).val();
refreshResults(($(this).attr("id")), showCardType);
});
$('#cardColor').change(function () {
alert("Color changed");
var showCardColor = $(this).val();
refreshResults(($(this).attr("id")), showCardColor);
});
function refreshResults(filter, value) {
alert(filter);
$.get("@Url.Action("DisplayCardsResults", "Card")", {
_page: 1,
_sortOrder: "@ViewBag._sortOrder",
_filter: filter,
_searchValue: value
}, function(data) {
$("#resultTable").html(data);
});
}
});
</script>
function refreshResults
有点棘手,因为我必须弄清楚如何从javascript函数调用控制器方法并通过它传递数据。我喜欢stackOverflow!
然后我删除了@if(Model.Count > 0)
以外的所有内容,并将其置于我这样称呼的部分视图中:
<div id="resultsDiv">
@{
Html.RenderPartial("_ResultsTable", @Model);
}
</div>
然后,在我的控制器中,我不得不解决问题:
public ActionResult DisplayCardsResults(int? _page, string _sortOrder, string _filter = "", string _searchValue = "")
{
ViewBag._searchValue = _searchValue;
ViewBag._filter = _filter;
if (Request.HttpMethod != "GET")
{
_page = 1;
}
int pageNumber = (_page ?? 1);
if (Request.IsAjaxRequest())
{
switch (_filter)
{
// The mListCardsToShow is an inner list I keep and it is different from the mListCards because of the where clause which flush the rest of the data.
case "cardRarity":
if (_searchValue == "All")
{
mListCardsToShow = mListCards.ToList();
}
else
{
mListCardsToShow.AddRange(mListCards.Where(_item => _item.mMasterCard.mCardRarity == _searchValue));
}
break;
case "cardType":
if (_searchValue == "All")
{
mListCardsToShow = mListCards.ToList();
}
else
{
mListCardsToShow.AddRange(mListCards.Where(_item => _item.mMasterCard.mCardType == _searchValue));
}
break;
case "cardColor":
if (_searchValue == "All")
{
mListCardsToShow = mListCards.ToList();
}
else
{
mListCardsToShow.AddRange(mListCards.Where(_item => _item.mMasterCard.mCardColor == _searchValue));
}
break;
default:
mListCardsToShow = mListCards.ToList();
break;
}
return PartialView("_ResultsTable", mListCardsToShow.ToPagedList(pageNumber, ValueDomain.PAGE_SIZE));
}
return View(mListCards.ToPagedList(pageNumber, ValueDomain.PAGE_SIZE));
}
现在,我必须承认排序并不完美,比如,我需要考虑每个过滤器的三个,但这是另一个故事。事情很有效,我为此感到高兴!
答案 0 :(得分:3)
这肯定听起来像是AJAX可以帮助您解决问题并使事情变得更优雅的事情 - 值得做一些研究。现在,只要用户单击其中一个链接,就需要重新加载整页才能简单地获取表中下一页的数据。您可以在需要时动态更新表格。
查看jQuery.ajax的文档 - 在传递给服务器的URL中,您可以设置过滤器(分页和排序),在成功处理程序中,您将更新表中的值。也不要被术语JSON吓倒,这只是js主要用于数据存储的术语,您可以在控制器上设置一个动作,该动作将返回JSON中的信息,该信息在AJAX成功处理程序中处理。 / p> PS:Yay MtG,祝你好运:)
答案 1 :(得分:2)
如果您有很多值,加载整个列表通常不是一个好主意。在你的情况下,尽管50个记录并不多,但通常不是一个有效的设计。 看看以下文章。
http://demo.aspnetawesome.com/GridDemo/CustomQuerying
http://www.4guysfromrolla.com/articles/012611-1.aspx
此外,Mvc还有一个开箱即用的WebGrid,通常适用于此类场景。 可能会满足您的需求。
http://msdn.microsoft.com/en-us/magazine/hh288075.aspx
希望它有所帮助。
答案 2 :(得分:1)
+1 Tyler。 AJAX是我能想到的唯一优雅方式。每次更改下拉列表时都必须将页面提交给服务器,并且您将获得数据,但每次没有AJAX时页面都会刷新。
修改强>
这是你使用ajax的方法。
这是您的观点
@using MyApp.Models
@model PagedList.IPagedList<MyApp.Utilities.CardDisplay>
<h2>
Cards Display Results
</h2>
<script type="text/javascript">
$(document).ready(function(){
$('#cardRarity').change(function () {
var showCardRarity = $(this).val();
refreshResults(($(this).attr("id")),showCardRarity );
});
$('#cardType').change(function() {
var showCardType = $(this).val();
refreshResults(($(this).attr("id")),showCardRarity );
});
$('#cardColor').change(function() {
var showCardColor = $(this).val();
refreshResults(($(this).attr("id")),showCardRarity );
});
function refreshResults(filter, value){
$.get("YourController/DisplayCardsResults",
{
_page = 1,
_sortOrder = ViewBag._currentSort,
_filter = filter,
_searchValue = value
},
function (data{
$("#resultsDiv").html(data);
}
});
</script>
@using (Html.BeginForm())
{
<p>Filter by rarity: <select name="cardRarity" id="cardRarity" tabindex="1">
<option value="All">All</option>
<option value="Land">Land</option>
<option value="Common">Common</option>
<option value="Uncommon">Uncommon</option>
<option value="Rare">Rare</option>
<option value="Mythic Rare">Mythic Rare</option>
<option value="Special">Special</option>
</select>
Filter by type: <select name="cardType" id="cardType" tabindex="2">
<option value="All">All</option>
<option value="Artifact">Artifact</option>
<option value="Instant">Instant</option>
<option value="Creature">Creature</option>
<option value="Land">Land</option>
<option value="Planeswalker">Planeswalker</option>
<option value="Enchantment">Enchantment</option>
<option value="Sorcery">Sorcery</option>
<option value="Tribal">Tribal</option>
</select>
Filter by color: <select name="cardColor" id="cardColor" tabindex="3">
<option value="All">All</option>
<option value="White">White</option>
<option value="Red">Red</option>
<option value="Blue">Blue</option>
<option value="Green">Green</option>
<option value="Black">Black</option>
<option value="Gold">Gold</option>
<option value="Colorless">Colorless</option>
</select>
</p>
}
<div id="resultsDiv">
@Html.RenderPartial("_ResultsTable",@Model)
<div>
将其放在部分视图_ResultsTable
中@using MyApp.Models
@model PagedList.IPagedList<MyApp.Utilities.CardDisplay>
@if (Model.Count > 0)
{
if (Model.PageCount > 1)
{
<div class="center">
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "DisplayCardsResults", new { _page = 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
@Html.Raw(" ")
@Html.ActionLink("< Prev", "DisplayCardsResults", new { _page = Model.PageNumber - 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "DisplayCardsResults", new { _page = Model.PageNumber + 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
@Html.Raw(" ")
@Html.ActionLink(">>", "DisplayCardsResults", new { _page = Model.PageCount, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>
}
<table id="resultTable">
<tr>
<th>Item number</th>
<th>Card Name</th>
<th>Number</th>
<th>Color</th>
<th>Mana Cost</th>
<th>Mana Converted</th>
<th>Card Type</th>
<th>Power</th>
<th>Toughness</th>
<th>Rarity</th>
<th>Card Set</th>
<th>Artist Name </th>
<th>Actions </th>
</tr>
@for (int i = 0; i < Model.Count; i++)
{
var className = i % 2 == 0 ? "even" : "odd";
var row = ((i + 1) + ((Model.PageNumber - 1) * 50));
<tr class="@className cardRarity cardRarity-@(Model[i].mCardRarity.Replace(" ", "-"))
cardType cardType-@(Model[i].mStrippedCardType)
cardColor cardColor-@(Model[i].mCardColor)">
<td>@row</td>
<td class="center">
@(Model[i].mCardFlagFace == CardInfo.FlagFaceValue.Normal ?
Html.ActionLink(Model[i].mCardName, "CardDetails", new {_cardId = Model[i].mCardID}) :
Html.ActionLink(Model[i].mCardName + " // " + Model[i].mChildCard.mCardName, "CardDetails", new {_cardId = Model[i].mCardID}))
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardNumber)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardColor)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardManaCost)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardManaConverted)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardType)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardPower)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardToughness)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardRarity)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardSet.mCardSetName)
</td>
<td>
@Html.DisplayFor(_item => _item[i].mCardArtistName)
</td>
<td>
@Html.ActionLink("Details", "Details", new {@_cardId = Model[i].mCardID})
@Html.ActionLink("Edit", "Edit", new {@_cardId = Model[i].mCardID})
@Html.ActionLink("Delete", "Delete", new {@_cardId = Model[i].mCardID})
</td>
</tr>
}
</table>
if (Model.PageCount > 1)
{
<div class="center">
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of @Model.PageCount
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<<", "DisplayCardsResults", new { _page = 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
@Html.Raw(" ")
@Html.ActionLink("< Prev", "DisplayCardsResults", new { _page = Model.PageNumber - 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
}
else
{
@:<<
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "DisplayCardsResults", new { _page = Model.PageNumber + 1, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
@Html.Raw(" ")
@Html.ActionLink(">>", "DisplayCardsResults", new { _page = Model.PageCount, _sortOrder = ViewBag._currentSort, _filter = ViewBag._filter, _searchValue = ViewBag._searchValue })
}
else
{
@:Next >
@Html.Raw(" ")
@:>>
}
</div>
}
}
在控制器中执行以下操作:
public ActionResult DisplayCardsResults(int _page, string _sortOrder, string _filter = "", string _searchValue = "")
{
ViewBag._filter = _filter;
ViewBag._searchValue= _searchValue;
//Do whatever you are doing to get the cards but to the resultant collection add the following where condition, suppose the collection is in var cards
switch (_filter)
{
case "cardRarity":
cards = cards.Where(s => s.CardRarity == _searchValue);
break;
case "cardType":
cards = cards.Where(s => s.CardType == _searchValue);
break;
case "cardColor":
cards = cards.Where(s => s.CardColor == _searchValue);
break;
default:
// no filter
break;
}
if(Request.isAjaxRequest)
return PartialView("_ResultsTable",cards);
return View(cards);
}