C# 使用带有LinkButton和ViewState的ObjectDataSource对ListView进行排序

C# 使用带有LinkButton和ViewState的ObjectDataSource对ListView进行排序,c#,asp.net,listview,viewstate,objectdatasource,C#,Asp.net,Listview,Viewstate,Objectdatasource,我正在使用ListView显示分页数据: ... ... 数据源定义: ... 后面的相关代码由以下两种方法组成: public IEnumerable<ListDocumentsResult> SelectItems( int maximumRows, int startRowIndex) { var results = Controller.ListDocuments(new ListDocumentsRequest()); Proper

我正在使用ListView显示分页数据:


...
...
数据源定义:


...
后面的相关代码由以下两种方法组成:

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();
    }
}
public IEnumerable SelectItems(
int最大行数,
int startRowIndex)
{
var results=Controller.ListDocuments(新的ListDocumentsRequest());
财产信息或财产;
尝试
{
sortProperty=typeof(ListDocumentsResult).GetProperty((字符串)ViewState[“mainListSortColumn”]);
}
抓住
{
sortProperty=null;
}
Func sortFunction=sortProperty==null
?(Func)(ldr=>ldr.lastUpdateDate)
:(ldr=>sortProperty.GetValue(ldr,新对象[0]);
返回
(sortProperty==null | |!((bool)ViewState[“mainListSortAsc”])
?results.OrderByDescending(排序函数)
:results.OrderBy(sortFunction))
.Skip(startRowIndex)
.取(最大行数);
}
受保护的无效SortItems(对象发送方,CommandEventArgs e)
{
if(e.CommandName==“SortMainList”)
{
var sortColumn=(字符串)e.CommandArgument;
如果((字符串)视图状态[“mainListSortColumn”]==sortColumn)
{
ViewState[“mainListSortAsc”]=!(bool)ViewState[“mainListSortAsc”];
}
其他的
{
ViewState[“mainListSortAsc”]=true;
ViewState[“mainListSortColumn”]=sortColumn;
}
数据绑定();
}
}
因此,我的意图是:当用户单击“名称”列标题中包含的
LinkButton
时(为了清晰起见,我省略了除一列以外的所有列),调用
SortItems
方法:它将排序的列名和排序顺序设置为
视图状态
,然后使用
DataBind
方法重新加载
ListView
。在
ObjectDataSource
的Select方法中,我们读取这个
ViewState
值,并使用它们对数据进行排序

将断点放在所有这些方法上,当我单击
链接按钮时,我可以看到调用序列:

  • OnLoad
  • SortItems
  • SelectItems
我遇到的问题是,当我使用
SelectItems
方法时,
ViewState
完全为空(它有0个键):如果我在页面的Load方法上设置断点,我会看到包含所有这些内容的控件只加载一次。
DataBind
方法似乎不会触发控件的任何加载,它似乎只是触发控件新实例的
SelectItems
方法(这意味着,如果我没有使用
ViewState
,而是在
SortItems
方法中设置了一个实例字段,那么当进入
SelectItems
方法时,该字段为空)

我确信
ViewState
在页面上处于活动状态(例如,我可以使用Firefox扩展在浏览器端找到
ViewState
键)


我不太清楚页面/控件的生命周期。有人能解释一下它是什么吗?

有很多更简单的方法

首先,不是自定义的
命令名
,而是将一个内置名称放入排序链接按钮中。该名称为
排序

那么你有

   <asp:LinkButton ID="SortByName" runat="server" CommandArgument="Name" CommandName="Sort" />
然后将数据提供程序方法修改为:

 public IEnumerable<ListDocumentsResult> SelectItems(
   string OrderBy,
   int maximumRows,
   int startRowIndex)
这也很简单

请注意,动态linq中存在一个小错误(或不便之处)——当排序顺序为空时,它会抛出一个异常

然后查找此代码(第47行及以下)

并手动将其更改为

    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");

完成。

有很多更简单的方法

首先,不是自定义的
命令名
,而是将一个内置名称放入排序链接按钮中。该名称为
排序

那么你有

   <asp:LinkButton ID="SortByName" runat="server" CommandArgument="Name" CommandName="Sort" />
然后将数据提供程序方法修改为:

 public IEnumerable<ListDocumentsResult> SelectItems(
   string OrderBy,
   int maximumRows,
   int startRowIndex)
这也很简单

请注意,动态linq中存在一个小错误(或不便之处)——当排序顺序为空时,它会抛出一个异常

然后查找此代码(第47行及以下)

并手动将其更改为

    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");

完成。

如果
SelectMethod
不是静态的,则
ObjectDataSource
控件将创建
TypeName
中指定类型的新实例,并对该实例调用该方法


您需要将排序表达式的参数添加到select方法并在
ObjectDataSource
上设置,或者需要处理并将
ObjectInstance
设置到现有控件实例。

如果
SelectMethod
不是静态的,则
ObjectDataSource
控件将创建一个新的在
TypeName
中指定的类型的实例,并调用该实例上的方法


您需要将排序表达式的参数添加到select方法中,并在
ObjectDataSource
上设置,或者需要处理并将
ObjectInstance
设置到现有控件实例。

感谢您提供了详尽的答案。由于我想不起来的原因,我认为SortParameterName属性处于启用状态当ObjectDataSource与GridView(与ListView相反)一起使用时使用。但不,它实际上是按照您所说的那样工作的。我还没有研究Dynamic.cs,所以我当然还需要修改代码来处理“Name DESC”的情况,-这并没有使我的代码变得更漂亮…但它可以工作。您不需要修改任何东西。正如我所说的“Name”和“Name DESC”将在