首先说明gridview是支持自动翻页和排序的(地球人都知道...), 但打多数开发情况数据源都是我们后台来绑定的,这样就不支持自动排序和翻页了。
搜索到很多扩展gridview自动排序的,但到实际应用时发现有很多的不足,而且大多只支持dataset,要想支持list(of T)类型的泛类型的很少,自己写了个,记录一下。
- Imports System
- Imports System.Collections.Generic
- Imports System.ComponentModel
- Imports System.Text
- Imports System.Web
- Imports System.Web.UI
- Imports System.Web.UI.WebControls
- Imports System.Data
- Imports System.Reflection
- Imports Logonexpress.DataService
- <ToolboxBitmap(GetType(GridView)), ToolboxData("<{0}:GridView runat=server></{0}:GridView>")> _
- Public Class GridView
- Inherits WebControls.GridView
- Public Delegate Sub BindHandler()
- Private data As Object
- Public Property DataSetSource() As Object '定义数据源
- Get
- If data IsNot Nothing Then
- Return data
- End If
- Return Nothing
- End Get
- Set(ByVal value As Object)
- Me.data = value
- End Set
- End Property
- '排序字段
- Protected Property SortExpressionStr() As String
- Get
- Return ViewState("SortExpression")
- End Get
- Set(ByVal value As String)
- ViewState("SortExpression") = value
- End Set
- End Property
- '获取排序表达式
- Protected ReadOnly Property SortExpressionEx() As String
- Get
- If SortExpressionStr Is Nothing Then Return Nothing
- Return Me.SortExpressionStr + " " + Me.SortDirectionStr
- End Get
- End Property
- '获取排序方向
- Protected Property SortDirectionStr() As String
- Get
- If ViewState("SortDirection") Is Nothing Then
- Return "DESC"
- End If
- If ViewState("SortDirection").ToString.ToLower = "asc" OrElse ViewState("SortDirection").ToString.ToLower = "desc" Then
- Return ViewState("SortDirection")
- End If
- Return "DESC"
- End Get
- Set(ByVal value As String)
- ViewState("SortDirection") = value
- End Set
- End Property
- '第一次翻页要还原排序方向,因为排序后我们就改变了排序方向,翻页时会重新绑定,所以要还原上一次的排序状态
- Private Property IsPaging() As Boolean
- Get
- Return ViewState("IsPaging")
- End Get
- Set(ByVal value As Boolean)
- ViewState("IsPaging") = value
- End Set
- End Property
- <Category("Appearance")> _
- <Editor("System.Web.UI.Design.ImageUrlEditor", GetType(System.Drawing.Design.UITypeEditor))> _
- <Description("设置升序图标"), Browsable(True)> _
- Public Property AscendingImageUrl() As String
- Get
- If ViewState("SortImageAsc") IsNot Nothing Then
- Return ViewState("SortImageAsc")
- End If
- Return ""
- End Get
- Set(ByVal value As String)
- ViewState("SortImageAsc") = value
- End Set
- End Property
- <Category("Appearance")> _
- <Editor("System.Web.UI.Design.ImageUrlEditor", GetType(System.Drawing.Design.UITypeEditor))> _
- <Description("设置降序图标"), Browsable(True)> _
- Public Property DescendingImageUrl() As String
- Get
- If ViewState("SortImageDesc") IsNot Nothing Then
- Return ViewState("SortImageDesc")
- End If
- Return ""
- End Get
- Set(ByVal value As String)
- ViewState("SortImageDesc") = value
- End Set
- End Property
- '重写OnRowCreateed来设置排序图标
- Protected Overrides Sub OnRowCreated(ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
- If e.Row.RowType = DataControlRowType.Header Then
- If Me.SortExpressionEx <> "" OrElse Me.SortExpressionEx <> String.Empty Then
- ShowSortImage(e.Row)
- End If
- End If
- End Sub
- Private Sub ShowSortImage(ByVal row As GridViewRow)
- For Each tc As TableCell In row.Cells
- If tc.Controls.Count > 0 And TypeOf tc.Controls(0) Is LinkButton Then
- Dim st As String = DirectCast(tc.Controls(0), LinkButton).CommandArgument
- If st = Me.SortExpressionStr Then
- Dim img As New System.Web.UI.WebControls.Image
- img.ImageUrl = IIf(Me.SortDirectionStr = "ASC", Me.AscendingImageUrl, Me.DescendingImageUrl)
- tc.Controls.Add(img)
- Exit Sub
- End If
- End If
- Next
- End Sub
- '重写排序方法
- Protected Overrides Sub OnSorting(ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs)
- Me.SortExpressionStr = e.SortExpression
- IsPaging = True
- RaiseEvent GetBindData()
- If Me.SortDirectionStr.ToLower = "asc" Then
- Me.SortDirectionStr = "DESC"
- Else
- Me.SortDirectionStr = "ASC"
- End If
- End Sub
- '顺便重写一下翻页方法,之后只要在代码中允许翻页就可以了
- Protected Overrides Sub OnPageIndexChanging(ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
- If Me.IsPaging Then
- SortDirectionStr = IIf(SortDirectionStr = "ASC", "DESC", "ASC")
- IsPaging = False
- End If
- Me.PageIndex = e.NewPageIndex
- RaiseEvent GetBindData()
- End Sub
- '获得数据源
- Public Event GetBindData()
- '重点:如果是List(of T)类型的数据源,就要把T类型传过来,在排序接口中使用
- Public Sub OnBind(Of T)(Optional ByVal pageIndex As Integer = 0)
- If Me.data IsNot Nothing Then
- If SortExpressionStr = Nothing Then
- Me.DataSource = data
- Me.DataBind()
- Exit Sub
- End If
- Select Case data.GetType.ToString
- Case GetType(DataSet).ToString
- Dim dv As DataView = DirectCast(data, DataSet).Tables(0).DefaultView
- dv.Sort = Me.SortExpressionEx
- Case GetType(DataTable).ToString
- Dim dv As DataView = DirectCast(data, DataTable).DefaultView
- dv.Sort = Me.SortExpressionEx
- Case Else
- Dim perwr As New PredicateWrapper()
- perwr.PropertyName = Me.SortExpressionStr
- perwr.IsAsc = Me.SortDirectionStr.ToUpper = "ASC"
- DirectCast(data, List(Of T)).Sort(AddressOf perwr.Comparsion(Of T))
- End Select
- Me.DataSource = data
- Me.PageIndex = pageIndex
- Me.DataBind()
- End If
- End Sub
- End Class
List排序类
- Imports Logonexpress.DataService
- Public Class PredicateWrapper
- Public PropertyName As String
- Public IsAsc As Boolean
- Public Sub New()
- End Sub
- Public Sub New(ByVal propertyname As String, ByVal isAsc As Boolean)
- propertyname = propertyname
- isAsc = isAsc
- End Sub
- Public Function Comparsion(Of T)(ByVal x As T, ByVal y As T) As Integer
- If x Is Nothing AndAlso y Is Nothing Then
- Return 0
- ElseIf x Is Nothing Then
- Return -1
- ElseIf y Is Nothing Then
- Return 1
- End If
- Dim getter As MemberGetDelegate = MemberAccessor.Instance.GetterDelegate(GetType(T), PropertyName)
- Dim vx As Object = getter(x)
- Dim vy As Object = getter(y)
- Dim result1 As Integer = comparer.Default.Compare(vx, vy)
- If result1 <> 0 Then
- If Not IsAsc Then
- Return Not result1
- Else
- Return result1
- End If
- End If
- Return 0
- End Function
- End Class
说明: 部分命名空间和类是引用公司的.
之后只要在代码中添加:Gridview就已经支持List和Dataset数据源的排序和分页了。
- Protected Sub GridView1_GetBindData() Handles GridView1.GetBindData
- Me.GridView1.DataSetSource = GetDb.GetDb
- Me.GridView1.OnBind(Of DataTable)()
- End Sub