[.NET]讓 DataGrid 中的流水號欄位依排序的順序走(Always 1, 2, 3 ...)

要如何讓 DataGrid 中的流水號欄位依排序的順序走(Always 1, 2, 3 ...)
如何知道 DataGrid 何時排序完成呢?
可以在 DataGrid 排序後,做某些事嗎?

環境

.NET 1.1, Windows Form, VB.NET

問題

要在 DataGrid Sort 後,修改原本流水號(例如:c1)的值,讓它依排序的流水號走(Always 1, 2, 3....)

目前 DataGrid 的流水號欄位,會因為依其他欄位排序,同時流水號會不同,如下,

image

客戶想要的是 DataGrid 的流水號欄位 Always 是 1, 2, 3 ….. 如下,

image

 

已知條件

DataGrid 的 DataSource 為 DataTable

 

研究及實作

本來想找看看DataGrid之中是否有排序的事件可以處理,後來參考到「Sorting DataGrid programmatically」。

在 DataGrid 的 Header 中按下 Click 排序時,會 Trigger Data的 ListChanged 事件

所以可以在 Data 的 DataView ListChanged 事件中來重新建立一個 DataTable,同時重新設定流水號欄位的值。

再將這個處理過的 DataTable Bind給 DataGrid。

所以在畫面上拉一個 DataGrid (DataGrid1),再拉一個 Button(btnBindData) ,在 Click 事件中模擬將查詢結果 Bind 到 DataGrid 上。

程式如下,

'要處理排序的DataGrid
Private BindingGrid As DataGrid = Nothing

'流水號欄位名稱
Private GridSeqNoColumnName As String = "c1"

Private Sub btnBindData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBindData.Click
	'取得Search 的結果 
	Dim dtSearchResult As DataTable = GetSearchResult()

	'Bind DataSource
	DataGrid1.DataSource = dtSearchResult

	'要處理的 DataGrid
	BindingGrid = DataGrid1
	'流水號欄位名稱
	GridSeqNoColumnName = "c1"

	'設定Grid排序後要處理的事件, 一開始沒有排序欄位
	BindDataSortEvent(dtSearchResult, AddressOf OnGridSorted, String.Empty)
End Sub

'建立測試的資料
Private Function GetSearchResult() As DataTable
	Dim dtResult As New DataTable
	dtResult.Columns.Add("c1", GetType(Int32))
	dtResult.Columns.Add("c2", GetType(String))
	dtResult.Columns.Add("c3", GetType(String))

	For i As Integer = 1 To 10
		dtResult.Rows.Add(New Object() {i, i.ToString(), 10 * i})
	Next
	Return dtResult
End Function

'設定 DataGrid 排序後,要處理的事件
Private Sub BindDataSortEvent(ByRef dt As DataTable, _
	ByRef changeEvent As System.ComponentModel.ListChangedEventHandler, _
	ByVal sortColumn As String)
	Dim list As DataView = dt.DefaultView
	'設定DataView的Sort欄位
	list.Sort = sortColumn
	AddHandler list.ListChanged, changeEvent
End Sub

'當DataGrid排序後,要處理流水號問題
Private Sub OnGridSorted(ByVal sender As Object, _
	ByVal args As System.ComponentModel.ListChangedEventArgs)
	Dim sortView As DataView = CType(sender, DataView)
	Dim orgSortColumn As String = sortView.Sort
	If orgSortColumn = GridSeqNoColumnName Then
		'在流水號的話,就不用再處理
		Return
	End If

	Dim sortedData As DataTable = ReAssignDataViewSeqNoValue(sortView, GridSeqNoColumnName)

	BindingGrid.DataSource = sortedData
	'設定Grid排序後要處理的事件
	BindDataSortEvent(sortedData, AddressOf OnGridSorted, orgSortColumn)
End Sub

'依DataView的排序,重新設定流水號的值,並回傳DataTable
Private Function ReAssignDataViewSeqNoValue(ByRef dv As DataView, ByVal sewNoColumnName As String) As DataTable
	Dim result As DataTable = dv.Table.Clone
	Dim dvItems As IEnumerator = dv.GetEnumerator
	Dim seqNo As Integer = 0
	While (dvItems.MoveNext())
		seqNo += 1
		Dim drv As DataRowView = dvItems.Current
		Dim newRow As DataRow = result.Rows.Add(drv.Row.ItemArray)
		newRow(sewNoColumnName) = seqNo
	End While
	Return result
End Function

image

 

參考資料

Sorting DataGrid programmatically

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^