0

ページ分割されたデータを表示するために ListView を使用しています。

<asp:ListView ID="listOfItems" runat="server" DataSourceID="ItemsDataSource" EnableModelValidation="True" InsertItemPosition="FirstItem" ItemPlaceholderID="ItemRowContainer">
    <LayoutTemplate>
        <div class="tablecontainer">
            <div class="pagination-top">
                <custom:TablePaginationControl ID="TablePaginationControl1" runat="server" ControlID="listOfItems" ShowPageSizeList="true" />
            </div>
            <table class="list-view">
                <tr>
                    <th class="first-column" width="350px">
                        <asp:LinkButton ID="SortByName" runat="server" CommandArgument="Name" CommandName="SortMainList" OnCommand="SortItems" Text="<%$ Resources:Name %>"></asp:LinkButton>
                    </th>
                    ...
                </tr>
                <tbody>
                    <tr runat="server" id="ItemRowContainer" />
                </tbody>
            </table>
        </div>
    </LayoutTemplate>
    ...
</asp:ListView>

データソース定義:

<asp:ObjectDataSource ID="ItemsDataSource" runat="server" EnablePaging="True" InsertMethod="AddItems" SelectCountMethod="SelectItemsCount" SelectMethod="SelectItems" TypeName="SHLCentral.TheLibrary.Web.View.DocumentManagementControl, ClientPortal.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd2852a10d692fb9" UpdateMethod="UpdateItems">
    ...
</asp:ObjectDataSource>

Revelant のコード ビハインドは、次の 2 つのメソッドで構成されています。

public IEnumerable<ListDocumentsResult> SelectItems(
    int maximumRows,
    int startRowIndex)
{
    var results = Controller.ListDocuments(new ListDocumentsRequest());

    PropertyInfo sortProperty;
    try
    {
        sortProperty = typeof (ListDocumentsResult).GetProperty((string) ViewState["mainListSortColumn"]);
    }
    catch
    {
        sortProperty = null;
    }
    Func<ListDocumentsResult, object> sortFunction = sortProperty == null
                            ? (Func<ListDocumentsResult, object>) (ldr => ldr.LastUpdatedDate)
                            : (ldr => sortProperty.GetValue(ldr, new object[0]));

    return
        (sortProperty == null || !((bool) ViewState["mainListSortAsc"])
             ? results.OrderByDescending(sortFunction)
             : results.OrderBy(sortFunction))
            .Skip(startRowIndex)
            .Take(maximumRows);
}

protected void SortItems(object sender, CommandEventArgs e)
{
    if (e.CommandName == "SortMainList")
    {
        var sortColumn = (string) e.CommandArgument;
        if ((string)ViewState["mainListSortColumn"] == sortColumn)
        {
            ViewState["mainListSortAsc"] = !(bool)ViewState["mainListSortAsc"];
        }
        else
        {
            ViewState["mainListSortAsc"] = true;
            ViewState["mainListSortColumn"] = sortColumn;
        }
        DataBind();
    }
}

したがって、私の意図は次のとおりです。ユーザーがLinkButton「名前」列ヘッダーに含まれるをクリックすると(わかりやすくするために、1列を除いてすべて省略しました)、SortItemsメソッドが呼び出されます:ソートされた列名とソート順をに設定しViewState、リロードしますメソッドをListView使用しDataBindます。の Select メソッドで、この値ObjectDataSourceを読み取り、それらを使用してデータを並べ替えます。ViewState

これらすべてのメソッドにブレークポイントを設定すると、 をクリックすると、次の一連の呼び出しがあることがわかりますLinkButton

  • OnLoad
  • SortItems
  • SelectItems

私が抱えている問題は、SelectItemsメソッドに到達したときにViewState完全に空である (キーが 0 である) ことです。ページの Load メソッドにブレークポイントを設定すると、これらすべてを含むコントロールが 1 回だけ読み込まれます。DataBindメソッドはコントロールの読み込みをトリガーしていないようです。コントロールの新しいインスタンスのメソッドをトリガーしているだけのようです(SelectItemsつまり、を使用する代わりにViewState、メソッドにインスタンス フィールドを設定するSortItemsと、フィールドは null になります)。メソッドに入るときSelectItems)。

ページで がアクティブになっていることは確かです(たとえば、Firefox 拡張機能を使用してブラウザー側でキーをViewState見つけることができます)。ViewState

ページ/コントロールのライフサイクルについて、私にははっきりしないことがあります。誰かが私にそれが何であるかを説明できますか?

4

2 に答える 2

3

はるかに単純なアプローチが存在します。

まず、カスタムの代わりにCommandName、組み込みの名前を並べ替えリンク ボタンに配置します。名前はSort

あなたはそれから

   <asp:LinkButton ID="SortByName" runat="server" CommandArgument="Name" CommandName="Sort" />

次に、を次のようObjectDataSourceに追加します。SortParameterNameOrderBy

   <ObjectDataSource .... SortParameterName="OrderBy" />

次に、データ プロバイダー メソッドを次のように変更します。

 public IEnumerable<ListDocumentsResult> SelectItems(
   string OrderBy,
   int maximumRows,
   int startRowIndex)

データ ソースは、コマンド引数 ( ) に基づいて値を自動的に提供し、コマンド ボタンを 2 回目にクリックするたびNameに自動的に追加されます(これは、ビューステートの並べ替え順序の状態が自動的に保持されるためです。これを再発明する必要があります!)DESCListView

次に、linq の文字列で並べ替えるために、この醜いデリゲートは必要ありません。代わりに、Dynamic Linq ライブラリをダウンロードします。

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

ファイルを見つけてプロジェクトに含めると、文字列を受け入れ、(!)を自動的にサポートするDynamic.csなど、多数の linq 演算子が追加されます。OrderByDESC

あなたはただ

 public IEnumerable<ListDocumentsResult> SelectItems(
   string OrderBy,
   int maximumRows,
   int startRowIndex)
 {

     Controller.ListDocuments(new ListDocumentsRequest())
        .OrderBy(OrderBy)
        .Skip(startRowIndex)
        .Take(maximumRows);
 }

これはとても簡単です!

ただし、動的 ​​linq には小さなバグ (または不都合) があることに注意してください。並べ替え順が空の場合、例外がスローされます。

次に、このコードを見つけます (47 行目以降)

    public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) {
        if (source == null) throw new ArgumentNullException("source");
        if (ordering == null) throw new ArgumentNullException("ordering");

手動で変更します

    public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) {
        if ( string.IsNullOrEmpty( ordering ) ) return source;
        if (source == null) throw new ArgumentNullException("source");
        if (ordering == null) throw new ArgumentNullException("ordering");

終わり。

于 2012-11-07T13:39:25.397 に答える
2

SelectMethodが静的でない場合、ObjectDataSourceコントロールは で指定された型の新しいインスタンスを作成し、TypeNameそのインスタンスでメソッドを呼び出します。

ソート式のパラメーターを select メソッドに追加して のSortParameterNameプロパティを設定するか、イベントObjectDataSourceを処理して を既存のコントロール インスタンスに設定する必要があります。ObjectCreatingObjectInstance

于 2012-11-07T13:41:46.500 に答える