1

私は MVC-App を構築しており、私のビューでページングを行う効率的な方法を探しています。

これまでのところ、次のページング システムをインストールしました。ただし、このページング システムがうまく機能する場合、欠点があります。ビューに表示されるリストは完全なリストではなく、ページ番号に基づいてユーザーが表示しているリストの部分です。欠陥は、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>

JavaScript 関数からコントローラー メソッドを呼び出してデータを渡す方法を理解する必要があったため、これfunction refreshResultsは少し注意が必要でした。スタックオーバーフロー大好き!

次に、 を超えるものをすべて削除し、それを次の@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));
}

ここで、並べ替えが完全ではないことを認めなければなりません。たとえば、フィルターの 3 つそれぞれを考慮する必要がありますが、それは別の話です。物事はうまくいき、私はそれで満足しています!

4

3 に答える 3

3

これは確かに、AJAX が問題を解決し、物事をよりエレガントにするのに役立つもののように思えます。調査する価値があります。現在、ユーザーがリンクの 1 つをクリックするたびに、テーブル内の次のページに相当するデータを取得するために、ページ全体をリロードする必要があります。代わりに、必要に応じてテーブルのみを動的に更新できます。

jQuery.ajaxのドキュメントを確認してください。サーバーに渡す URL でフィルター (ページネーションと並べ替え) を設定でき、成功ハンドラーでテーブルの値を更新できます。また、JSON という用語に惑わされないでください。JSON は、主に js で使用されるデータ ストレージの用語にすぎません。コントローラーでアクションを設定し、AJAX 成功ハンドラーで処理される JSON で情報を返すことができます。

PS: イェーイ MtG、頑張ってください :)

于 2013-07-23T17:55:40.133 に答える
2

多くの値がある場合、通常、リスト全体をロードすることはお勧めできません。あなたの場合、50 レコードは多くはありませんが、一般的に従うべき効率的な設計ではありません。以下の記事をご覧ください。

http://demo.aspnetawsome.com/GridDemo/CustomQuerying

http://kevww.wordpress.com/2011/12/20/how-to-implement-paging-sorting-in-mvc-3-part-2-how-to-use-it-for-paging-sorting/

http://www.4guysfromrolla.com/articles/012611-1.aspx

また、Mvc には、通常、このタイプのシナリオに適したすぐに使用できる WebGrid があります。あなたのニーズに合うかもしれません。

http://stick2basic.wordpress.com/2013/03/18/effective-paging-and-sorting-with-webgrid-web-helper-asp-net-mvc/

http://msdn.microsoft.com/en-us/magazine/hh288075.aspx

それが役に立てば幸い。

于 2013-07-23T17:50:53.273 に答える
1

タイラーに+1。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);
}
于 2013-07-23T19:44:24.810 に答える