是否可以在GridView上进行自定义排序

时间:2010-01-13 16:11:29

标签: asp.net gridview sorting

我需要对需要复杂排序的 GridView (非DataGridView,它不是同一件事)进行排序,我不知道如何完成它。我有两列,一列包含日期,另一列包含优先级。

如果日期小于或等于今天的日期。我想首先按优先顺序排序,然后按日期排序。如果日期大于今天的日期,我想先按日期排序,然后按优先顺序排序。

假设totay是2010-jan-13,这样订购的一些数据可能看起来像这些

   date       priority  Explanation
-----------   --------  --------------------------------------------
2010-jan-13      3      This comes first because it has the higer priority of all items whith a date <= today
2010-jan-12      2      Since this items and the next have the same priority they're ordered by date
2010-jan-13      2
2010-jan-14      5      This item and the followings have date > today, so they are ordered by date then by priority.
2010-jan-14      0
2010-jan-15      5
2010-jan-16      5

无论如何都要手动对网格视图进行排序或传递比较仿函数吗?

编辑: 数据源是DataTable。

4 个答案:

答案 0 :(得分:3)

您需要对数据源进行排序,而不是对GridView进行排序。 (告诉我们您的数据源,我们可以提供帮助。它是DataTable,SqlDataSource,业务对象吗?)

在GridView Web服务器控件中对数据进行排序 http://msdn.microsoft.com/en-us/library/hwf94875.aspx

自定义排序

如果默认排序行为不足以满足您的要求,您可以自定义网格的排序行为。自定义排序的基本技术是处理Sorting事件。在处理程序中,您可以执行以下操作:

  • 自定义传递给数据源控件的排序表达式。默认情况下,排序表达式是单个列的名称。您可以在事件处理程序中修改排序表达式。例如,如果要按两列排序,则可以创建包含两者的排序表达式。然后,您可以将修改后的排序表达式传递给数据源控件。有关更多信息,请参阅GridViewSortEventArgs .. ::。SortExpression属性。

  • 创建自己的排序逻辑。例如,如果您正在使用不支持排序的数据源,您可以在自己的代码中执行排序,然后将网格绑定到排序数据。

排序示例(未经测试且未使用LINQ [故意])

Dim oDataSet As DataSet = GatherDataSet()
Dim oDataTable As DataTable = oDataSet.Tables(0)
Dim oSort1 As New DataView(oDataTable, "Date > #2010/01/13#", "Date, Priority", DataViewRowState.CurrentRows)
Dim oSort2 As New DataView(oDataTable, "Date <= #2010/01/13#", "Priority, Date", DataViewRowState.CurrentRows)
Dim oGridDataTable As DataTable
oGridDataTable = oSort1.ToTable
oGridDataTable.Merge(oSort2.ToTable)

oGridView.DataSource = oGridDataTable

'...
'you can then merge any changes back into the data set, if needed
oDataSet.Merge(oGridDataTable)

答案 1 :(得分:0)

Salut Mathieu,

假设您使用的是DataSource并且每个元素都是一个类(而不是数据行),您可以将IComparable实现到您的类中。它添加了CompareTo方法,您可以在其中决定每个元素如何相互比较。

class DatePriority: IComparable
{
    private DateTime date;
    public DateTime Date
    {
        get { return date; }
    }
    private int priority;
    public int Priority
    {
        get { return priority; }
    }

    public DatePriority(DateTime date, int priority)
    {
        this.date = date;
        this.priority = priority;
    }

    public int CompareTo(object obj)
    {
        if (obj is DatePriority)
        {
            DatePriority comparedDatePriority = obj as DatePriority;

            // Comparison logic
            // If the compared elements are today or before today, order by priority in descending order. Same priorities are ordered by date in ascending order
            // If the compared elements are for the future, order by date in ascending order. Same dates are order by priority in descending order
            if ((this.Date <= DateTime.Today && comparedDatePriority.Date <= DateTime.Today))
            {
                if (Priority == comparedDatePriority.Priority)
                    return Date.CompareTo(comparedDatePriority.Date);
                else
                    return -Priority.CompareTo(comparedDatePriority.Priority);
            }
            else
            {                    
                if (Date == comparedDatePriority.date)
                    return -Priority.CompareTo(comparedDatePriority.Priority); // Descending order
                else
                    return Date.CompareTo(comparedDatePriority.Date);
            }
        }
        throw new ArgumentException("Not a DatePriority");
    }
}    

答案 2 :(得分:0)

是的,你可以做到。这是你如何做到的。

假设您有一个GridView,它从BusinessLayer方法中调用记录。我将把UserManager的例子作为业务层代理类。

    [DataObjectAttribute()]
    public static class UserManager
    {
        [DataObjectMethod(DataObjectMethodType.Select, true)]
        public static UserCollection GetUsers()
        {
            return UserDB.GetAll();
        }

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public static UserCollection GetUsers(string sortExpression)
        {
            UserCollection users = UserDB.GetAll();
            users.Sort(new EntityComparer<User>(sortExpression));
            return users;
        }
    }

在过载的GetUsers方法中查看这行代码。

users.Sort(new EntityComparer<User>(sortExpression));

我为业务对象编写了Generic Comparer实现。 EntityComparer只是一个实现IComparer接口的泛型类。您可以编写自己的Comparer实现[实现IComparer接口]并将其称为上面的代码。

以下是我的GridView的样子......

         <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
                <asp:BoundField DataField="UserName" HeaderText="UserName" 
                    SortExpression="UserName" />
                <asp:BoundField DataField="Password" HeaderText="Password" 
                    SortExpression="Password" />
                <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
                <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
                <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" 
                    SortExpression="CompanyName" />
            </Columns>
        </asp:GridView>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
            OldValuesParameterFormatString="original_{0}" SelectMethod="GetUsers" 
            TypeName="FilePark.BusinessLayer.UserManager"></asp:ObjectDataSource>

另请注意,GridView将在回发时传递sortExpression并调用重载方法。

答案 3 :(得分:-1)

dataGrinView的排序过程使用数据源的Sort过程。 要手动排序实现IBindingListView的数据创建类,请按照您的意愿实现它的排序方法,并在DataGridView中将此类用作DataSource