VB.NET中ListView加载数据和排序功能的实现
平时我们在VB.NET中开发数据库相关的程序都会用到DataGrid来显示数据,它的使用相对简单,也有排序的功能,基本能满一般的要求。但有时它并不能满足项目的功能需求,这时我们就想到了用ListView,虽然它的功能正是我们所要的,必竞它不是一个数据库的控件,不能像DataGrid那样通过简单的设置就可以显示数据,同时也没有排序的功能,这些就要我们自已用程序代码来实现了。前些天在开发一个项目时就写了一段使用ListView显示数据并实现排序的代码,简单地说一下它的实现原理:显示数据是通过循环读取数据记录,用ListView的Add方法将数据添加到ListView中;排序的功能是通过ListView列的点击事件来得到要排序的字段,再使用ORDER BY关键字组合SQL重新加载数据来实现排序的。欢迎使用VB.NTE的朋友一起交流,我的EMAIL是[email protected]。
以下是程序所使用的数据库及控件的设置信息:
数据库名:Northwind(SQL SERVER 2000中自带的,如果没有此数据库请先建立)
表 名:Products(如果没有这个表,请使用后面附带的SQL语句建立)
窗 体 名:frmListViewDb
所用控件
Label 1个
属性:Text=ProductName:
-----------------------------------------------------
TextBox 1个
属性:Name=txtProductName
-----------------------------------------------------
Button 5个
(1) 属性:Name=btnFilter、Text=过滤
(2) 属性:Name=btnShowAll、Text=全部
(3) 属性:Name=btnSelAll、Text=全选
(4) 属性:Name=btnCancelSelAll、Text=取消全选
(5) 属性:Name=btnInsteadSel、Text=反选
(5) 属性:Name=btnInfo、Text=查看
ListView 1个
属性:Name=ListViewDb、View=Details、Sorting=None、GridLines=True,FullRowSelect=True,CheckBoxs=True,Size=856,416、Columns添加10个列,Width=150,Text分别为:ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued
源程序:
Imports System.Data.SqlClient
Public Class frmListViewDb
Inherits System.Windows.Forms.Form
'定义数据库连接对象
Dim sdConn As New SqlConnection
Dim conString As String = "data source=127.0.0.1;initial catalog=Northwind;uid=sa;password=123456"
'定义记录db2ListView执行状态的变量
Dim Dbr As Integer
'定义记录默认排序方式的变量
Dim mySort As String = "ASC"
'定义记录默认排序字段的变量
Dim myField As String = "ProductID"
'定义记录上次排序的字段在LISTVIEW中的列ID的变量
Dim pOrderID As Integer = 0
'定义复选操作的相关变量
Dim i As Integer
Dim sCount As Integer
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'窗体重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer
'注意: 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Friend WithEvents txtProductName As System.Windows.Forms.TextBox
Friend WithEvents btnFilter As System.Windows.Forms.Button
Friend WithEvents btnShowAll As System.Windows.Forms.Button
Friend WithEvents ListViewDb As System.Windows.Forms.ListView
Friend WithEvents ColumnHeader1 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader2 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader3 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader4 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader5 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader6 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader7 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader8 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader9 As System.Windows.Forms.ColumnHeader
Friend WithEvents ColumnHeader10 As System.Windows.Forms.ColumnHeader
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents btnSelAll As System.Windows.Forms.Button
Friend WithEvents btnCancelSelAll As System.Windows.Forms.Button
Friend WithEvents btnInsteadSel As System.Windows.Forms.Button
Friend WithEvents btnInfo As System.Windows.Forms.Button
Me.ListViewDb = New System.Windows.Forms.ListView
Me.ColumnHeader1 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader2 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader3 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader4 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader5 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader6 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader7 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader8 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader9 = New System.Windows.Forms.ColumnHeader
Me.ColumnHeader10 = New System.Windows.Forms.ColumnHeader
Me.txtProductName = New System.Windows.Forms.TextBox
Me.btnFilter = New System.Windows.Forms.Button
Me.btnShowAll = New System.Windows.Forms.Button
Me.Label1 = New System.Windows.Forms.Label
Me.btnSelAll = New System.Windows.Forms.Button
Me.btnCancelSelAll = New System.Windows.Forms.Button
Me.btnInsteadSel = New System.Windows.Forms.Button
Me.btnInfo = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'ListViewDb
'
Me.ListViewDb.CheckBoxes = True
Me.ListViewDb.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader1, Me.ColumnHeader2, Me.ColumnHeader3, Me.ColumnHeader4, Me.ColumnHeader5, Me.ColumnHeader6, Me.ColumnHeader7, Me.ColumnHeader8, Me.ColumnHeader9, Me.ColumnHeader10})
Me.ListViewDb.FullRowSelect = True
Me.ListViewDb.GridLines = True
Me.ListViewDb.Location = New System.Drawing.Point(8, 64)
Me.ListViewDb.Name = "ListViewDb"
Me.ListViewDb.Size = New System.Drawing.Size(856, 416)
Me.ListViewDb.TabIndex = 0
Me.ListViewDb.View = System.Windows.Forms.View.Details
'
'ColumnHeader1
'
Me.ColumnHeader1.Text = "ProductID"
Me.ColumnHeader1.Width = 100
'
'ColumnHeader2
'
Me.ColumnHeader2.Text = "ProductName"
Me.ColumnHeader2.Width = 150
'
'ColumnHeader3
'
Me.ColumnHeader3.Text = "SupplierID"
Me.ColumnHeader3.Width = 150
'
'ColumnHeader4
'
Me.ColumnHeader4.Text = "CategoryID"
Me.ColumnHeader4.Width = 150
'
'ColumnHeader5
'
Me.ColumnHeader5.Text = "QuantityPerUnit"
Me.ColumnHeader5.Width = 150
'
'ColumnHeader6
'
Me.ColumnHeader6.Text = "UnitPrice"
Me.ColumnHeader6.Width = 150
'
'ColumnHeader7
'
Me.ColumnHeader7.Text = "UnitsInStock"
Me.ColumnHeader7.Width = 150
'
'ColumnHeader8
'
Me.ColumnHeader8.Text = "UnitsOnOrder"
Me.ColumnHeader8.Width = 150
'
'ColumnHeader9
'
Me.ColumnHeader9.Text = "ReorderLevel"
Me.ColumnHeader9.Width = 150
'
'ColumnHeader10
'
Me.ColumnHeader10.Text = "Discontinued"
Me.ColumnHeader10.Width = 150
'
'txtProductName
'
Me.txtProductName.Font = New System.Drawing.Font("宋体", 12.0!)
Me.txtProductName.Location = New System.Drawing.Point(88, 16)
Me.txtProductName.Name = "txtProductName"
Me.txtProductName.Size = New System.Drawing.Size(200, 26)
Me.txtProductName.TabIndex = 1
Me.txtProductName.Text = ""
'
'btnFilter
'
Me.btnFilter.Location = New System.Drawing.Point(296, 16)
Me.btnFilter.Name = "btnFilter"
Me.btnFilter.Size = New System.Drawing.Size(75, 26)
Me.btnFilter.TabIndex = 2
Me.btnFilter.Text = "过滤"
'
'btnShowAll
'
Me.btnShowAll.Location = New System.Drawing.Point(384, 16)
Me.btnShowAll.Name = "btnShowAll"
Me.btnShowAll.Size = New System.Drawing.Size(75, 26)
Me.btnShowAll.TabIndex = 3
Me.btnShowAll.Text = "全部"
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(8, 21)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(80, 16)
Me.Label1.TabIndex = 4
Me.Label1.Text = "ProductName:"
'
'btnSelAll
'
Me.btnSelAll.Location = New System.Drawing.Point(472, 16)
Me.btnSelAll.Name = "btnSelAll"
Me.btnSelAll.Size = New System.Drawing.Size(75, 26)
Me.btnSelAll.TabIndex = 5
Me.btnSelAll.Text = "全选"
'
'btnCancelSelAll
'
Me.btnCancelSelAll.Location = New System.Drawing.Point(560, 16)
Me.btnCancelSelAll.Name = "btnCancelSelAll"
Me.btnCancelSelAll.Size = New System.Drawing.Size(65, 26)
Me.btnCancelSelAll.TabIndex = 6
Me.btnCancelSelAll.Text = "取消全选"
'
'btnInsteadSel
'
Me.btnInsteadSel.Location = New System.Drawing.Point(640, 16)
Me.btnInsteadSel.Name = "btnInsteadSel"
Me.btnInsteadSel.Size = New System.Drawing.Size(75, 26)
Me.btnInsteadSel.TabIndex = 7
Me.btnInsteadSel.Text = "反选"
'
'btnInfo
'
Me.btnInfo.Location = New System.Drawing.Point(728, 16)
Me.btnInfo.Name = "btnInfo"
Me.btnInfo.Size = New System.Drawing.Size(75, 26)
Me.btnInfo.TabIndex = 7
Me.btnInfo.Text = "查看"
'
'frmListViewDb
'
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
Me.ClientSize = New System.Drawing.Size(872, 493)
Me.Controls.Add(Me.btnInsteadSel)
Me.Controls.Add(Me.btnCancelSelAll)
Me.Controls.Add(Me.btnSelAll)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.btnShowAll)
Me.Controls.Add(Me.btnFilter)
Me.Controls.Add(Me.txtProductName)
Me.Controls.Add(Me.ListViewDb)
Me.Controls.Add(Me.btnInfo)
Me.Name = "frmListViewDb"
Me.Text = "ListView加载数据排序功能"
Me.ResumeLayout(False)
End Sub
#End Region
'***************************************************************************
'函数功能:将读取出来的数据写入LISTVIEW中
'函数名称:sd_Db2Listview,调用格式:sd_Db2Listview("A"),sd_Db2Listview("")
'参 数:FilerStr,要查询的产品名,为空时则查询所有的
'返 回 值:1为正常,-1为有错误
'编 写 者:SD
'日 期:2005-9-23
'转载请保留此信息
'***************************************************************************
Private Function sd_Db2Listview(ByVal FilerStr As String) As Integer
Try
Cursor.Current = Cursors.WaitCursor
'清除LISTVIEW中已有的数据
ListViewDb.Items.Clear()
Dim varSQL As String
'定义数据库操作对象
Dim cmd As SqlCommand
Dim rd As SqlDataReader
'定义LISTVIEW中的项目,用于写入数据
Dim lsv As ListViewItem
'建立数据库连接
sdConn = New SqlConnection(conString)
sdConn.Open()
'构造查询及排序的SQL语句
If FilerStr.Length > 0 Then
varSQL = "SELECT * FROM Products WHERE ProductName LIKE '" & FilerStr & "%' ORDER BY " & myField & " " & mySort & ";"
Else
varSQL = "SELECT * FROM Products ORDER BY " & myField & " " & mySort & ";"
End If
'读取数据
cmd = New SqlCommand(varSQL, sdConn)
rd = cmd.ExecuteReader
'写入数据到LISTVIEW中
While rd.Read
lsv = New ListViewItem(rd("ProductID").ToString)
lsv.SubItems.Add(rd("ProductName").ToString)
lsv.SubItems.Add(rd("SupplierID").ToString)
lsv.SubItems.Add(rd("CategoryID").ToString)
lsv.SubItems.Add(rd("QuantityPerUnit").ToString)
lsv.SubItems.Add(rd("UnitPrice").ToString)
lsv.SubItems.Add(rd("UnitsInStock").ToString)
lsv.SubItems.Add(rd("UnitsOnOrder").ToString)
lsv.SubItems.Add(rd("ReorderLevel").ToString)
lsv.SubItems.Add(rd("Discontinued").ToString)
ListViewDb.Items.Add(lsv)
End While
sdConn.Close()
Cursor.Current = Cursors.Default
Return sd_Db2Listview = 1
Catch ex As Exception
MessageBox.Show(ex.ToString)
Return sd_Db2Listview = -1
Finally
If sdConn.State = ConnectionState.Open Then
sdConn.Close()
End If
End Try
End Function
'启动时即显示所有数据
Private Sub frmListViewDb_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dbr = sd_Db2Listview("")
End Sub
'过滤显示数据
Private Sub btnFilter_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFilter.Click
Try
Dim FilerStr As String = ""
FilerStr = txtProductName.Text.Trim().Replace("'", "")
dbr=sd_Db2Listview(FilerStr)
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
If sdConn.State = ConnectionState.Open Then
sdConn.Close()
End If
End Try
End Sub
'显示所有数据
Private Sub btnShowAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowAll.Click
sd_Db2Listview("")
End Sub
'处理排序
Private Sub ListViewDb_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListViewDb.ColumnClick
'根据点击的列ID,得到排序的字段名
Select Case e.Column.ToString
Case 0
myField = "ProductID"
Case 1
myField = "ProductName"
Case 2
myField = "SupplierID"
Case 3
myField = "CategoryID"
Case 4
myField = "QuantityPerUnit"
Case 5
myField = "UnitPrice"
Case 6
myField = "UnitsInStock"
Case 7
myField = "UnitsOnOrder"
Case 8
myField = "ReorderLevel"
Case 9
myField = "Discontinued"
End Select
'清除上次排序列的标记
ListViewDb.Columns(pOrderID).Text = ListViewDb.Columns(pOrderID).Text.Replace(" ▼", "").Replace(" ▲", "")
'显示排序方式
If mySort = "ASC" Then
ListViewDb.Columns(e.Column.ToString).Text = ListViewDb.Columns(e.Column.ToString).Text & " ▼"
mySort = "DESC"
Else
mySort = "ASC"
ListViewDb.Columns(e.Column.ToString).Text = ListViewDb.Columns(e.Column.ToString).Text & " ▲"
End If
'重新加载数据
sd_Db2Listview(txtProductName.Text.Trim())
ListViewDb.Refresh()
'记住上次排序的列ID,以便清除,否则将会出现排序过的列都有排序的标记
pOrderID = e.Column.ToString
End Sub
'全选
Private Sub btnSelAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSelAll.Click
sCount = ListViewDb.Items.Count - 1
For i = 0 To sCount
ListViewDb.Items(i).Checked = True
Next i
End Sub
'取消全选
Private Sub btnCancelSelAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelSelAll.Click
sCount = ListViewDb.Items.Count - 1
For i = 0 To sCount
ListViewDb.Items(i).Checked = False
Next i
End Sub
'反选
Private Sub btnInsteadSel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInsteadSel.Click
sCount = ListViewDb.Items.Count - 1
For i = 0 To sCount
If ListViewDb.Items(i).Checked Then
ListViewDb.Items(i).Checked = False
Else
ListViewDb.Items(i).Checked = True
End If
Next i
End Sub
'得到复选框选择的ID
Private Sub btnInfo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInfo.Click
Dim SelLst As String = ""
Dim unSelLst As String = ""
sCount = ListViewDb.Items.Count - 1
For i = 0 To sCount
If ListViewDb.Items(i).Checked Then
SelLst = SelLst & ListViewDb.Items(i).SubItems(0).Text.ToString() & ","
Else
unSelLst = unSelLst & ListViewDb.Items(i).SubItems(0).Text.ToString() & ","
End If
Next i
If SelLst.Length > 0 Then
MsgBox("复选框选中的记录ID有:" & SelLst, MsgBoxStyle.Information)
End If
If unSelLst.Length > 0 Then
MsgBox("复选框未选中的记录ID有:" & unSelLst, MsgBoxStyle.Information)
End If
End Sub
End Class
附:
生成Products表的SQL语句:
CREATE TABLE [dbo].[Products] (
[ProductID] [int] IDENTITY (1, 1) NOT NULL ,
[ProductName] [nvarchar] (40) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SupplierID] [int] NULL ,
[CategoryID] [int] NULL ,
[QuantityPerUnit] [nvarchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[UnitPrice] [money] NULL ,
[UnitsInStock] [smallint] NULL ,
[UnitsOnOrder] [smallint] NULL ,
[ReorderLevel] [smallint] NULL ,
[Discontinued] [bit] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Products] ADD
CONSTRAINT [DF_Products_UnitPrice] DEFAULT (0) FOR [UnitPrice],
CONSTRAINT [DF_Products_UnitsInStock] DEFAULT (0) FOR [UnitsInStock],
CONSTRAINT [DF_Products_UnitsOnOrder] DEFAULT (0) FOR [UnitsOnOrder],
CONSTRAINT [DF_Products_ReorderLevel] DEFAULT (0) FOR [ReorderLevel],
CONSTRAINT [DF_Products_Discontinued] DEFAULT (0) FOR [Discontinued],
CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED
(
[ProductID]
) ON [PRIMARY] ,
CONSTRAINT [CK_Products_UnitPrice] CHECK ([UnitPrice] >= 0),
CONSTRAINT [CK_ReorderLevel] CHECK ([ReorderLevel] >= 0),
CONSTRAINT [CK_UnitsInStock] CHECK ([UnitsInStock] >= 0),
CONSTRAINT [CK_UnitsOnOrder] CHECK ([UnitsOnOrder] >= 0)
GO
ALTER TABLE [dbo].[Products] ADD
CONSTRAINT [FK_Products_Categories] FOREIGN KEY
(
[CategoryID]
) REFERENCES [dbo].[Categories] (
[CategoryID]
),
CONSTRAINT [FK_Products_Suppliers] FOREIGN KEY
(
[SupplierID]
) REFERENCES [dbo].[Suppliers] (
[SupplierID]
)
GO