当使用未绑定数据更新单元格时,DataGridView 将行移至底部
DataGridView moves rows to bottom when cell is updated with Unbound data
我有一个用代码设置样式并使用 SQLite 数据库中的数据的 DataGridView
数据库未绑定到 DataGridView。当我点击一行时会触发一些事件。
首先数据库更新为今天的日期。
包含该日期的单元格反映了更改。
然后我根据单元格值对列进行排序。使用此代码
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
如果我从填充 DataGridView 的子例程 ViewSearches() 中省略这些代码行,则该过程按预期工作,没有问题。
If rowCount <= 25 Then
maxRowCount = 25 - rowCount
For iA = 1 To maxRowCount
dgvLinks.Rows.Add(" ")
Next
End If
如果我调用用 ViewSearches() 重新填充 DataGridView,我可以使用这些空行
我试图避免这种设计,因为它似乎过度使用了资源。
发生的错误是包含数据的 4 行被移动到 DataGridView 的底部,而这 4 行数据上方是空行。我将post下面的相关代码。
我的问题 如何保留空行并填充 DataGridView,以便包含数据的行位于 DataGridView 的顶部?
这是我选择 LID 2 后的屏幕截图。它已更新并冒泡到 DGV 的底部。
Private Sub ViewSearches()
Dim intID As Integer
Dim strChannelName As String
Dim strLinkAddress As String
Dim strLastVisit As String
Dim strLinkType As String
Dim rowCount As Integer
Dim maxRowCount As Integer
'Dim emptyStr As String = " "
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;")
conn.Open()
Using cmd As New SQLiteCommand("", conn)
'cmd.CommandText = "SELECT * FROM LinkTable"
' Line of CODE Above works with If statement in While rdr
'==========================================================
'cmd.CommandText = "SELECT * FROM LinkTable WHERE ytSiteType = 'News'"
cmd.CommandText = "SELECT * FROM LinkTable WHERE ytSiteType = @site"
cmd.Parameters.Add("@site", DbType.String).Value = gvSLT
Using rdr As SQLite.SQLiteDataReader = cmd.ExecuteReader
'dgvLinks.DataSource = rdr
'Statement Above use when DB is bound to dgvLinks
'=================================================
While rdr.Read()
intID = CInt((rdr("LID")))
strChannelName = rdr("ytChannelName").ToString
strLinkAddress = rdr("ytLinkAddress").ToString
strLastVisit = rdr("ytLastVisit").ToString
strLinkType = rdr("ytSiteType").ToString
'If strLinkType = gvSLT Then
dgvLinks.Rows.Add(intID, strChannelName, strLinkAddress, strLastVisit)
rowCount = rowCount + 1
'End If
End While
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
End Using
If rowCount <= 25 Then
maxRowCount = 25 - rowCount
For iA = 1 To maxRowCount
dgvLinks.Rows.Add(" ")
Next
End If
End Using
End Using
'FindEmpty()
End Sub
更新数据库的点击事件
Private Sub dgvLinks_CellClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvLinks.CellClick
selRow = e.RowIndex
If e.RowIndex = -1 Then
gvalertType = "4"
frmAlert.ShowDialog()
Exit Sub
End If
'Dim col As DataGridViewColumn = Me.dgvLinks.Columns(e.ColumnIndex)
Dim row As DataGridViewRow = Me.dgvLinks.Rows(e.RowIndex)
If row.Cells(2).Value Is Nothing Then
gvalertType = "5"
frmAlert.ShowDialog()
Return
Exit Sub
ElseIf gvTxType = "View" Then
webPAGE = row.Cells(2).Value.ToString()
siteID = CInt(row.Cells(0).Value.ToString())
UpdateSiteData()
''MsgBox("Stop " & selRow)
'dgvLinks.ClearSelection()
'dgvLinks.Refresh()
'dgvLinks.RefreshEdit()
Process.Start(webPAGE)
'dgvLinks.Columns.Clear()
''dgvLinks.Rows.Clear()
''ViewSearches()
ElseIf gvTxType = "Delete" Or gvTxType = "Update" Then
gvID = CInt(row.Cells(0).Value)
gvSiteName = row.Cells(1).Value.ToString
gvSiteURL = row.Cells(2).Value.ToString
frmADE.Show()
Close()
End If
End Sub
更新例程
Public Sub UpdateSiteData()
Dim dateToday = Date.Today
dateToday = CDate(CDate(Date.Today).ToString("M-d-yyyy"))
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;"),
cmd As New SQLiteCommand("UPDATE LinkTable SET ytLastVisit = @ytLastVisit WHERE LID =" & siteID, conn)
conn.Open()
cmd.Parameters.Add("@ytLastVisit", DbType.String).Value = dateToday.ToString("M-d-yyyy")
cmd.ExecuteNonQuery()
dgvLinks.Rows(selRow).Cells(3).Value = dateToday.ToString("M-d-yyyy")
'Line of code above INSERTS value in Last Visit Column at the correct ROW
'NOT needed if you reload data from the database
'=========================================================================
'dgvLinks.Refresh()
'dgvLinks.RefreshEdit()
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
End Using
End Sub
你会看到很多我试过的东西都被注释掉了。
正如我所说,如果我调用 ViewSearches() 子例程,我可以解决问题。
Private Sub StyleDGV()
'Sets Design of the DataGridView
'===============================
dgvLinks.DefaultCellStyle.Font = New Font("Times New Roman", 13.0F, FontStyle.Bold)
dgvLinks.ColumnCount = 4
dgvLinks.Columns(0).Width = 60 'ID
dgvLinks.Columns(1).Width = 325 'Site Name 325
dgvLinks.Columns(2).Width = 860 'Site Url 860
dgvLinks.Columns(3).Width = 154 'LastVisit 140
'Option with no blank rows increase col count to 5
'OR increase width of col(3) WHY? because the scroll bar is not showing
' TOTAL Width 1450 Height 488
'=============================
'To Set Col Header Size Mode = Enabled
'To Set Col Header Default Cell Styles DO in Properties
'dgvLinks.Columns(6).DefaultCellStyle.Format = "c"
dgvLinks.ColumnHeadersHeight = 10 'Sans Serif 'Tahoma
dgvLinks.ColumnHeadersDefaultCellStyle.Font = New Font("Sans Serif", 12.0F, FontStyle.Bold)
dgvLinks.ColumnHeadersDefaultCellStyle.ForeColor = Color.Blue
dgvLinks.DefaultCellStyle.BackColor = Color.LightGoldenrodYellow
'DGV Header Names
dgvLinks.Columns(0).Name = "LID"
dgvLinks.Columns(1).Name = "Site Name"
dgvLinks.Columns(2).Name = "Site URL"
dgvLinks.Columns(3).Name = "Last Visit"
dgvLinks.Columns(0).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(1).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(2).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(3).SortMode = DataGridViewColumnSortMode.NotSortable
End Sub
任何关注此问题的人,允许保留空行的 FIX 只是在更新数据库子例程中省略排序命令
至于将数据从 SQLite DB 获取到网格中……您几乎可以在 ViewSearches
方法中完成。命令文本看起来不错;但是您使用的是 SQLiteDataReader
。这是逐行读取数据。
我建议您改用 SQLiteDataAdapter
。有了它,您可以一次性从数据库中获取 DataTable
。首先创建并初始化一个 DataSet
,然后创建一个新的 SQLiteDataAdapter
然后将您的命令添加到数据适配器,例如...
DataSet ds = new DataSet();
using (SQLiteDataAdapter sqlDA = new SQLiteDataAdapter()) {
conn.Open();
sqlDA.SelectCommand = cmd.CommanText;
sqlDA.Fill(ds, “tableName”);
if (ds.Tables.Count > 0) {
//return ds.Tables[“tableName”];
dgvLinks.DataSource = ds.Tables[“tableName”];
}
}
如果查询成功,这将向名为“tableName”的 DataSet
ds
添加一个 DataTable
。
然后简单地使用 DataTable
作为网格的 DataSource
……就像……
dgvLinks.DataSource = ds.Tables[“tableName”];
我有一个用代码设置样式并使用 SQLite 数据库中的数据的 DataGridView
数据库未绑定到 DataGridView。当我点击一行时会触发一些事件。
首先数据库更新为今天的日期。
包含该日期的单元格反映了更改。
然后我根据单元格值对列进行排序。使用此代码
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
如果我从填充 DataGridView 的子例程 ViewSearches() 中省略这些代码行,则该过程按预期工作,没有问题。
If rowCount <= 25 Then
maxRowCount = 25 - rowCount
For iA = 1 To maxRowCount
dgvLinks.Rows.Add(" ")
Next
End If
如果我调用用 ViewSearches() 重新填充 DataGridView,我可以使用这些空行
我试图避免这种设计,因为它似乎过度使用了资源。
发生的错误是包含数据的 4 行被移动到 DataGridView 的底部,而这 4 行数据上方是空行。我将post下面的相关代码。
我的问题 如何保留空行并填充 DataGridView,以便包含数据的行位于 DataGridView 的顶部?
这是我选择 LID 2 后的屏幕截图。它已更新并冒泡到 DGV 的底部。
Private Sub ViewSearches()
Dim intID As Integer
Dim strChannelName As String
Dim strLinkAddress As String
Dim strLastVisit As String
Dim strLinkType As String
Dim rowCount As Integer
Dim maxRowCount As Integer
'Dim emptyStr As String = " "
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;")
conn.Open()
Using cmd As New SQLiteCommand("", conn)
'cmd.CommandText = "SELECT * FROM LinkTable"
' Line of CODE Above works with If statement in While rdr
'==========================================================
'cmd.CommandText = "SELECT * FROM LinkTable WHERE ytSiteType = 'News'"
cmd.CommandText = "SELECT * FROM LinkTable WHERE ytSiteType = @site"
cmd.Parameters.Add("@site", DbType.String).Value = gvSLT
Using rdr As SQLite.SQLiteDataReader = cmd.ExecuteReader
'dgvLinks.DataSource = rdr
'Statement Above use when DB is bound to dgvLinks
'=================================================
While rdr.Read()
intID = CInt((rdr("LID")))
strChannelName = rdr("ytChannelName").ToString
strLinkAddress = rdr("ytLinkAddress").ToString
strLastVisit = rdr("ytLastVisit").ToString
strLinkType = rdr("ytSiteType").ToString
'If strLinkType = gvSLT Then
dgvLinks.Rows.Add(intID, strChannelName, strLinkAddress, strLastVisit)
rowCount = rowCount + 1
'End If
End While
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
End Using
If rowCount <= 25 Then
maxRowCount = 25 - rowCount
For iA = 1 To maxRowCount
dgvLinks.Rows.Add(" ")
Next
End If
End Using
End Using
'FindEmpty()
End Sub
更新数据库的点击事件
Private Sub dgvLinks_CellClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvLinks.CellClick
selRow = e.RowIndex
If e.RowIndex = -1 Then
gvalertType = "4"
frmAlert.ShowDialog()
Exit Sub
End If
'Dim col As DataGridViewColumn = Me.dgvLinks.Columns(e.ColumnIndex)
Dim row As DataGridViewRow = Me.dgvLinks.Rows(e.RowIndex)
If row.Cells(2).Value Is Nothing Then
gvalertType = "5"
frmAlert.ShowDialog()
Return
Exit Sub
ElseIf gvTxType = "View" Then
webPAGE = row.Cells(2).Value.ToString()
siteID = CInt(row.Cells(0).Value.ToString())
UpdateSiteData()
''MsgBox("Stop " & selRow)
'dgvLinks.ClearSelection()
'dgvLinks.Refresh()
'dgvLinks.RefreshEdit()
Process.Start(webPAGE)
'dgvLinks.Columns.Clear()
''dgvLinks.Rows.Clear()
''ViewSearches()
ElseIf gvTxType = "Delete" Or gvTxType = "Update" Then
gvID = CInt(row.Cells(0).Value)
gvSiteName = row.Cells(1).Value.ToString
gvSiteURL = row.Cells(2).Value.ToString
frmADE.Show()
Close()
End If
End Sub
更新例程
Public Sub UpdateSiteData()
Dim dateToday = Date.Today
dateToday = CDate(CDate(Date.Today).ToString("M-d-yyyy"))
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;"),
cmd As New SQLiteCommand("UPDATE LinkTable SET ytLastVisit = @ytLastVisit WHERE LID =" & siteID, conn)
conn.Open()
cmd.Parameters.Add("@ytLastVisit", DbType.String).Value = dateToday.ToString("M-d-yyyy")
cmd.ExecuteNonQuery()
dgvLinks.Rows(selRow).Cells(3).Value = dateToday.ToString("M-d-yyyy")
'Line of code above INSERTS value in Last Visit Column at the correct ROW
'NOT needed if you reload data from the database
'=========================================================================
'dgvLinks.Refresh()
'dgvLinks.RefreshEdit()
dgvLinks.Sort(dgvLinks.Columns(3), ListSortDirection.Ascending)
End Using
End Sub
你会看到很多我试过的东西都被注释掉了。
正如我所说,如果我调用 ViewSearches() 子例程,我可以解决问题。
Private Sub StyleDGV()
'Sets Design of the DataGridView
'===============================
dgvLinks.DefaultCellStyle.Font = New Font("Times New Roman", 13.0F, FontStyle.Bold)
dgvLinks.ColumnCount = 4
dgvLinks.Columns(0).Width = 60 'ID
dgvLinks.Columns(1).Width = 325 'Site Name 325
dgvLinks.Columns(2).Width = 860 'Site Url 860
dgvLinks.Columns(3).Width = 154 'LastVisit 140
'Option with no blank rows increase col count to 5
'OR increase width of col(3) WHY? because the scroll bar is not showing
' TOTAL Width 1450 Height 488
'=============================
'To Set Col Header Size Mode = Enabled
'To Set Col Header Default Cell Styles DO in Properties
'dgvLinks.Columns(6).DefaultCellStyle.Format = "c"
dgvLinks.ColumnHeadersHeight = 10 'Sans Serif 'Tahoma
dgvLinks.ColumnHeadersDefaultCellStyle.Font = New Font("Sans Serif", 12.0F, FontStyle.Bold)
dgvLinks.ColumnHeadersDefaultCellStyle.ForeColor = Color.Blue
dgvLinks.DefaultCellStyle.BackColor = Color.LightGoldenrodYellow
'DGV Header Names
dgvLinks.Columns(0).Name = "LID"
dgvLinks.Columns(1).Name = "Site Name"
dgvLinks.Columns(2).Name = "Site URL"
dgvLinks.Columns(3).Name = "Last Visit"
dgvLinks.Columns(0).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(1).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(2).SortMode = DataGridViewColumnSortMode.NotSortable
dgvLinks.Columns(3).SortMode = DataGridViewColumnSortMode.NotSortable
End Sub
任何关注此问题的人,允许保留空行的 FIX 只是在更新数据库子例程中省略排序命令
至于将数据从 SQLite DB 获取到网格中……您几乎可以在 ViewSearches
方法中完成。命令文本看起来不错;但是您使用的是 SQLiteDataReader
。这是逐行读取数据。
我建议您改用 SQLiteDataAdapter
。有了它,您可以一次性从数据库中获取 DataTable
。首先创建并初始化一个 DataSet
,然后创建一个新的 SQLiteDataAdapter
然后将您的命令添加到数据适配器,例如...
DataSet ds = new DataSet();
using (SQLiteDataAdapter sqlDA = new SQLiteDataAdapter()) {
conn.Open();
sqlDA.SelectCommand = cmd.CommanText;
sqlDA.Fill(ds, “tableName”);
if (ds.Tables.Count > 0) {
//return ds.Tables[“tableName”];
dgvLinks.DataSource = ds.Tables[“tableName”];
}
}
如果查询成功,这将向名为“tableName”的 DataSet
ds
添加一个 DataTable
。
然后简单地使用 DataTable
作为网格的 DataSource
……就像……
dgvLinks.DataSource = ds.Tables[“tableName”];