13

asp.net mvc でいくつかのグリッドを少し試しています。Microsoft は、mvc 3 のプレリリースであまりにもよく知っているグリッドを持っているので、それを試してみようと思いました。

基本的な機能は簡単に実装できますが、並べ替えに関してはいくつか問題があります。グリッドは、URL による並べ替えを処理します。URL には、次のように並べ替え列と並べ替え方向があります: ?sortdir=ASC&sort=ABONNEMENT

特定の列で並べ替えを行った後、その列の sortdir クエリ文字列が ?sortdir=DESC に変更されると予想されますが、そうではありません。?sortdir=ASC のままです。これがバグなのか機能なのか、またこれを解決する方法を知っている人はいますか?

もう 1 つの非常に面倒なこと: 並べ替えリンクをクリックすると、httpget 要求が実行されます。このため、モデルを失います。ページでグリッドをフィルター処理する可能性 (検索機能) があるため、これをモデルに保持したいと考えています。私の意見では、このデータをセッション状態に保存するよりも、モデル状態にする方がはるかに簡単でクリーンなソリューションです。http 投稿が実行されるように、ヘッダー リンクの並べ替えの動作を変更することは可能ですか?

これに関するアイデアや考えはありますか?助けてくれたTnx。

グリーツ、コーエン

ビューのコードは次のとおりです。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<table>
    <tr>
        <td>
            <h1 class="normal">List of subscription</h1>
        </td>
        <td>

        </td>
    </tr>
</table>
<% using (Html.BeginForm("List", "Subscription", FormMethod.Post)) { %>

<table border="0" cellpadding="0" cellspacing="5">
    <tr>
        <td>
            Search By
        </td>
        <td>
            <%: Html.DropDownListFor(m => m.SearchByColumn, Ogone.FrontEnd.Web.Controllers.SubscriptionController.SubscriptionSearchList) %>
        </td>
        <td>
            <%: Html.TextBoxFor(m => m.SearchByText) %>
        </td>
        <td>
            <input name="button" type="submit" value="Search" />
        </td>
    </tr>
</table>

<div>
<%  
var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList,  
              columnNames: new List<string>(){"Title"},  
              canPage:false);  
 %> 
<%= grid.GetHtml(columns: grid.Columns(
             grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ID })),
             grid.Column("ID"),
             grid.Column("ISP"),
             grid.Column("ABONNEMENT"),
             grid.Column("MODE"),
             grid.Column("SETUPFEE"),
             grid.Column("MONTHLYFEE"))
             ) %>
</div>

4

4 に答える 4

25

これは、グリッド列名がフィールドまたはプロパティに対応している必要があるために発生します。グリッドヘッダーにURLを生成するメソッドは、URLクエリ文字列からの「並べ替え」を境界付きの列およびグリッド列名と比較します。それらの3つは同じでなければなりません。列名の定義が適切に構成されていない場合、URLは正しく生成されません。

とにかく..ここに適切に定義された列名のいくつかの例があります。

ここに表示するサンプルドメインクラスがあります

public class Person
{
    public string FirstName;
    public string LastName;
    public Address LivesIn;
}

public class Address
{
    public string Country;
    public string City;
}

リストを表示してみましょう

列名をフィールドとして使用する

grid.Column("FirstName"),
grid.Column("LastName"),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

...すべての列に正しい並べ替えURLがあります

列名にタイプミスをすると、例外が発生します

grid.Column("FirstName"),
grid.Column("MyLastName"), <-- this throws exception
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

ただし、フォーマットを使用することはでき、例外はスローされません

grid.Column("FirstName"),
grid.Column("MyLastName", format: item => item.LastName</text>),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

...しかし、列MyLastNameのURLの並べ替えは不正になります!!! 常にsortDir=ASC

適切な並べ替えURLとカスタム形式を使用するには、適切な列名を使用する必要があります。

grid.Column("FirstName"),
grid.Column("LastName", format: item => item.LastName),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

... 全て大丈夫

複合型はどうですか?

grid.Column("FirstName"),
grid.Column("LastName"),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

....すごい...すべてが大丈夫です..それはバグの子供です..列"LivesIn.MyNonExistingField"には適切な並べ替えURLがあります。

わかりました...ドメイン構造を公開したくない場合はどうなりますか。次に、バインド中に列名のリストを追加する必要があります

var grid = new WebGrid(persons, columnNames: new [] { "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "Foo" });

grid.Column("Foo", format: item => item.FirstName),
grid.Column("LastName"),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

..Foo列に適切な並べ替えURLが追加されました

しかし、注意してください!!! 別のバグがあります。

バインディングに手動の列名を追加すると、手動の列が見つかるまですべての列がスキップされます。例 :

var grid = new WebGrid(persons, columnNames: new [] { "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "Foo" });

grid.Column("FirstName"),
grid.Column("Foo", format: item => item.LastName),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

...列「FirstName」のソートURLは正しく生成されません...sortDir= ASC常に...これを修正するには、次のように列名として「FirstName」も追加します。

var grid = new WebGrid(persons, columnNames: new [] { "FirstName", "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "FirstName", "Foo" });

grid.Column("FirstName"),
grid.Column("Foo", format: item => item.LastName),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

@コーヘン

ここでコード内のcolumnNamesを削除します

var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList,  
          columnNames: new List<string>(){"Title"},  
          canPage:false);

...または、「ID」、「ISP」などのすべての列名を追加します

于 2011-08-04T16:22:30.073 に答える
2

この問題の回避策を考えていたところ、見つけました。

追加のパラメーターをクエリ文字列コレクションに挿入します。そうすれば、検索フィルターをクエリ文字列に入れることができます。

通常、クエリ文字列コレクションは読み取り専用ですが、これを修正するコードを見つけました。

パラメータをクエリ文字列に追加するコード:

            public static void Add(string name, string value)
            {
                    NameValueCollection qs = System.Web.HttpContext.Current.Request.QueryString;
                    qs = (NameValueCollection)System.Web.HttpContext.Current.Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(System.Web.HttpContext.Current.Request);
                    PropertyInfo readOnlyInfo = qs.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
                    readOnlyInfo.SetValue(qs, false, null);
                    qs[name] = value;
                    readOnlyInfo.SetValue(qs, true, null);
            }

新しいコントローラー コード:

            public ActionResult Index(string SearchFilter)
            {
                    // check querystring search
                    if (string.IsNullOrEmpty(SearchFilter) && !String.IsNullOrEmpty(Request.QueryString["search"]))
                            SearchFilter = Request.QueryString["search"];

                    var model = new Models.SubscriptionListModel { SearchFilter = SearchFilter };

                    if (string.IsNullOrEmpty(SearchFilter))
                    {
                            model.SubscriptionList = _subscriptionHandler.ReadWhereIdLessThanThousand();
                    }
                    else
                    {
                            // add search filter to the querystring
                            Common.QueryString.Add("search", SearchFilter);
                            model.SubscriptionList = _subscriptionHandler.ReadWhereContains(SearchFilter);
                    }

                    if (Request.IsAjaxRequest())
                    {
                            return View("SubscriptionList", model);
                    }
                    else
                    {
                            return View("Index", model);
                    }
            }

誰かがこれを修正するためのよりクリーンなソリューションを持っている場合でも、提案は大歓迎です:-)

于 2011-12-08T08:32:17.520 に答える
1

DESC が ASC に切り替わらない理由がわかりません。同様の例があり、うまく機能します。ajax コンテナー ( ajaxUpdateContainerId ) を使用してみてください。これは、httpget リクエストで発生している問題を解決し、検索結果を維持する以外に何もない場合に役立ちます。これが私が持っているものです:(私はかみそりを使用していますが、変換するのは簡単なはずです)。

新しいプロパティ ajaxUpdateContainerId: " div_name "を追加するだけです。

div_nameの ID を持つ div でグリッドをラップします。

@{
var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList, canPage:false, ajaxUpdateContainerId: "grid");  
}
<div id="grid">
    @grid.GetHtml(columns: grid.Columns(  
    grid.Column(format:(item) => Html.ActionLink("Edit", "Edit", new { id=item.Id })),
    grid.Column("ISP"),
    grid.Column("ABONNEMENT"))) 
</div>

頑張ってください、お役に立てば幸いです!

于 2011-06-17T15:15:07.810 に答える