我使用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>
背后隐含的代码是由这两种方法构成的:
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
时(为清晰起见,我省略了一列除外),调用了SortItems
方法:将排序的列名称和排序顺序设置为ViewState
,然后使用ListView
方法重新加载DataBind
。在ObjectDataSource
的Select方法中,我们读取了这些ViewState
值并使用它们来订购数据。
在所有这些方法上设置断点,当我点击LinkButton
时,我可以看到这一系列的调用:
OnLoad
SortItems
SelectItems
我遇到的问题是,当我到达SelectItems
方法时,ViewState
完全为空(它有0个键):如果我在页面的Load方法上设置断点,我看到包含所有这一切的控件只加载一次。 DataBind
方法似乎没有触发任何控件的加载,它似乎只是触发控件的新实例的SelectItems
方法(意味着如果,而不是使用{{1} },我在ViewState
方法中设置了一个实例字段,当进入SortItems
方法时,该字段为空。
我确信SelectItems
在页面上处于活动状态(我可以使用Firefox扩展程序在浏览器端找到ViewState
个键)。
关于页面/控件的生命周期,我不太清楚。有人能解释一下这对我来说是什么吗?
答案 0 :(得分:3)
存在许多更简单的方法。
首先,您将一个内置名称放入排序链接按钮,而不是自定义CommandName
。名称为Sort
。
你有
<asp:LinkButton ID="SortByName" runat="server" CommandArgument="Name" CommandName="Sort" />
然后,在ObjectDataSource
上,您将SortParameterName
添加为OrderBy
:
<ObjectDataSource .... SortParameterName="OrderBy" />
然后将数据提供者方法修改为:
public IEnumerable<ListDocumentsResult> SelectItems(
string OrderBy,
int maximumRows,
int startRowIndex)
数据源将根据命令参数(Name
)自动提供值,并且每当您第二次单击命令按钮时它将自动附加DESC
(这是因为{{ 1}}自动保持其视图状态中的排序顺序状态,你不必重新发明它!)
然后,你不需要这个丑陋的代表按linq的字符串排序。而是下载Dynamic Linq库:
找到ListView
文件,将其包含在项目中,它将添加一堆额外的linq运算符,包括Dynamic.cs
,它接受字符串并自动支持OrderBy
(!)
然后你
DESC
这很简单!
请注意,动态linq中存在一个小错误(或不方便) - 当排序顺序为空时,它会抛出异常。
然后查找此代码(第47行及以下)
public IEnumerable<ListDocumentsResult> SelectItems(
string OrderBy,
int maximumRows,
int startRowIndex)
{
Controller.ListDocuments(new ListDocumentsRequest())
.OrderBy(OrderBy)
.Skip(startRowIndex)
.Take(maximumRows);
}
并手动将其更改为
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");
完成。
答案 1 :(得分:2)
如果SelectMethod
不是静态的,ObjectDataSource
控件将创建TypeName
中指定类型的新实例,并在该实例上调用该方法。
您需要为select方法添加排序表达式的参数,并在ObjectDataSource
上设置SortParameterName
property,或者您需要处理ObjectCreating
event并设置{{ 1}}到现有的控件实例。