我正在手動填充datagridview。所以沒有資料源或資料系結。
我AllowUserToAddRows堅持True_ AllowUserToDeleteRows_True
我的作業和代碼
當 Enter 鍵轉到右側的下一個單元格而不是向下時,我進行了調整以使用我的 datagridview。
Private WithEvents ec As DataGridViewTextBoxEditingControl
和,
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
If keyData = Keys.Tab AndAlso DgvGrid.EditingControl IsNot Nothing Then
Return True
Else
Return MyBase.ProcessCmdKey(msg, keyData)
End If
Return Nothing
End Function
還,
Private Sub dgvGrid_KeyDown(sender As Object, e As KeyEventArgs) Handles DgvGrid.KeyDown
Try
Dim iCol = DgvGrid.CurrentCell.ColumnIndex
Dim iRow = DgvGrid.CurrentCell.RowIndex
Select Case e.KeyCode
Case Keys.Return
e.Handled = True
If iCol = DgvGrid.Columns.Count - 1 Then
If DgvGrid.Rows(iRow).Cells("TCODE").Value = "" Then
MessageBox.Show("ENTER DETAILS AGAIN", MessageBoxButtons.OK, MessageBoxIcon.Warning)
DgvGrid.CurrentCell = DgvGrid("TREATMENT", iRow)
Else
DgvGrid.CurrentCell = DgvGrid("TREATMENT", iRow 1)
End If
Else
If iCol = 2 Then '#TREATMENT
If DgvGrid.Rows(iRow).Cells("TCODE").Value = "" Then
'CalculateData
Else
DgvGrid.CurrentCell = DgvGrid(iCol 1, iRow)
End If
ElseIf iRow = DgvGrid.Rows.Count - 1 Then
DgvGrid.Rows.Add() '------------- ISSUE IS HERE
'DgvGrid.BeginEdit(True)
Else
DgvGrid.CurrentCell = DgvGrid(iCol 1, iRow)
End If
End If
End Select
If e.Shift AndAlso e.KeyCode = Keys.Delete Then
If DgvGrid.SelectedCells.Count > 0 Then
DgvGrid.Rows.RemoveAt(DgvGrid.CurrentCell.RowIndex)
End If
End If
Catch ex1 As System.InvalidOperationException
MessageBox.Show("CANNOT DELETE LAST ROW.", "BONNY SOFTWARE", MessageBoxButtons.OK, MessageBoxIcon.Error)
Catch ex As Exception
MessageBox.Show("TAKE A PICTURE" & Environment.NewLine & "ERROR : " & ex.Message, "BONNY SOFTWARE", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
最后的,
Private Sub ec_PreviewKeyDown(ByVal sender As Object, ByVal e As PreviewKeyDownEventArgs) Handles ec.PreviewKeyDown
Try
Dim iCol = DgvGrid.CurrentCell.ColumnIndex
Dim iRow = DgvGrid.CurrentCell.RowIndex
Select Case e.KeyCode
Case Keys.Return
e.Handled = True
If iCol = DgvGrid.Columns.Count - 1 Then
If DgvGrid.Rows(iRow).Cells("TCODE").Value = "" Then
MessageBox.Show("ENTER DETAILS AGAIN", MessageBoxButtons.OK, MessageBoxIcon.Warning)
DgvGrid.CurrentCell = DgvGrid("TREATMENT", iRow)
Else
DgvGrid.CurrentCell = DgvGrid("TREATMENT", iRow 1)
End If
Else
If iCol = 2 Then '#TREATMENT
If DgvGrid.Rows(iRow).Cells("TCODE").Value = "" Then
'CalculateData
Else
DgvGrid.CurrentCell = DgvGrid(iCol 1, iRow)
End If
ElseIf iRow = DgvGrid.Rows.Count - 1 Then
DgvGrid.Rows.Add() '------------- ISSUE IS HERE
'DgvGrid.BeginEdit(True)
Else
DgvGrid.CurrentCell = DgvGrid(iCol 1, iRow)
End If
End If
End Select
If e.Shift AndAlso e.KeyCode = Keys.Delete Then
If DgvGrid.SelectedCells.Count > 0 Then
DgvGrid.Rows.RemoveAt(DgvGrid.CurrentCell.RowIndex)
End If
End If
Catch ex1 As System.InvalidOperationException
MessageBox.Show("CANNOT DELETE LAST ROW.", "BONNY SOFTWARE", MessageBoxButtons.OK, MessageBoxIcon.Error)
Catch ex As Exception
MessageBox.Show("TAKE A PICTURE" & Environment.NewLine & "ERROR : " & ex.Message, "BONNY SOFTWARE", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
請注意,當 cellEdit 處于活動狀態時,DatagridviewKeyDown和ec_PreviewKeyDown事件與我想要的效果相同。
ISSUE
當我在最后一行的最后一列并嘗試添加一行代碼時DgvGrid.Rows.Add(),該行被添加到上面,或者可能發生其他事情,將上面的行留空,如下圖所示

但是,如果我編輯單元格并鍵入一些內容,則會自動創建一個新的未提交行,并且在按下 Enter/Return 時它作業正常。如下圖所示

但即使 datagridviewCell 處于 EditMode,也不會生成新的未提交行。它僅在我鍵入內容或更改值時生成。
如果我只能得到未提交的行而不進行編輯,那么我的作業就完成了。
接受任何其他方法/建議。謝謝
uj5u.com熱心網友回復:
在我的小測驗中,我很好奇的一件事是“如何”將行添加到第一張圖片中的網格中?...

具體來說,最上面的第一個網格……在某種意義上看起來很奇怪…… “新行在哪里?” ...考慮到網格AllowUserToAdd行屬性設定為true...然后用戶顯然沒有將資料“鍵入”到網格中。
那么,我們只能假設資料是以編程方式添加到網格中的嗎?而且......我可以讓網格看起來如頂部所示的唯一方法是,如果我以編程方式將資料添加到網格中的單個單元格“新”并且只有行......類似于......
DgvGrid.Rows(0).Cells(0).Value = “SomeValue”….
正如我們所看到的,這很可能會顯示在最后一行,但是,手動將資料添加到網格的“新”行會出現問題……簡而言之……您不想這樣做。
您可以從您的示例中看到,如果您在“之后”某個時候“添加”一個新行,我們將資料添加到“新”行,那么,帶有我們之前添加的資料的行仍然在網格“新”行中……在剛剛添加的行下方……如您的圖片所示。
在沒有技術知識的情況下,網格“新”行是一個“特殊”行,并不是真正要以編程方式添加資料的行。例子; 如果您在網格的最后一個“新”行的單元格中鍵入單個字符……那么您會注意到,只要您在單元格中鍵入單個字符,網格就會“自動創建”一個新行和該行您剛剛輸入的不再是“新”行。當您的代碼手動將資料添加到“新”行時,不會觸發網格來創建“新”行。這就是您的代碼需要做的……即添加一個新行。
基本上,將資料添加到網格的代碼......做錯了。無論該代碼做什么,很明顯它應該首先添加一個新行,而不是以編程方式將資料添加到網格的“新”行。
此外,我之前看到過這樣的情況,當用戶按下“Enter”鍵時,您希望將網格選擇的行為更改為向右移動,而不是向下移動。我不會否認,它比看起來要復雜一些。下面的代碼將選擇向右移動,并在需要時添加一個新行,如下所示。

下面是我的方法,如果用戶按下“Enter”鍵,選擇將移動到右側的單元格而不是向下,此外......如果選擇位于 LAST “new”的最后一個單元格中”行,無論單元格是否處于編輯模式,并且用戶按下“Enter”鍵,然后,創建一個新行。我不一定會這樣做,因為如果用戶在最后一個“新”行上反復按下回車鍵,代碼將繼續添加“空”行。但我猜你想要這種行為。
為了簡化事情,我過去常常SendKeys“移動”選擇,而不是設定網格的CurrentCell行和列索引。換句話說,我們已經知道如果用戶按下“Enter”鍵,那么網格的“正常”選擇/CurrentCell 將“向下”移動到下一個單元格。所以,我們只需要發送一個“Tab”鍵,然后一個“UP”箭頭鍵就可以在右側獲得我們想要的選擇。
顯然,我們需要檢查邊界問題,例如最后一列和最后一個“新”行。在最后一列的情況下,網格的選擇會簡單地向下移動,我們只需要發送“HOME”鍵就可以選擇該行的第一個單元格。
如果選擇在最后一個“新”行和最后一列,那么我們可以假設該行的任何單元格中都沒有資料……如果用戶在該行的單元格中鍵入了資料,那么這個行不會是最后一行。因此,用戶必須多次按下“Enter”鍵,而無需在任何單元格中輸入任何文本……或者正如您所做的那樣……以編程方式將資料添加到“新”行。我們將假設代碼沒有像當前那樣執行此操作,而是按照應有的方式正確“添加”行。否則,新行將在您顯示的頂部。
因此,鑒于此并為了簡化代碼,我們將創建一個方法,當用戶按下“Enter”鍵時,將選擇移動到右側的單元格。
KeyDown當單元格不處于“編輯模式”時,GRIDS事件和單元格處于“編輯模式”時的單元TextBox格PreviewKeyDown事件都會呼叫此方法。這個方法只假設一件事……用戶只是按下了 ENTER 鍵。單元格是否處于編輯模式并不重要。
此MoveGridSelection方法可能類似于下面的演練。
Private Sub MoveGridSelection()
If DgvGrid.CurrentCell IsNot Nothing Then
If (DgvGrid.CurrentCell.ColumnIndex < DgvGrid.Columns.Count - 1) Then
If (Not (DgvGrid.CurrentCell.RowIndex = DgvGrid.NewRowIndex)) Then
SendKeys.Send("{Up}")
End If
SendKeys.Send("{Tab}")
Else ' current cell is LAST column
If (DgvGrid.CurrentCell.RowIndex = DgvGrid.NewRowIndex) Then
' last cell on last 'new' row - do nothing and stay there
' Or set the selection back to the top
' Or add a New row as below ..? Not a good idea IMO
DgvGrid.Rows.Add()
End If
SendKeys.Send("{Home}")
End If
End If
End Sub
演練:如果網格CurrentCell列索引小于列數,那么……通常我們可以發送“Tab”和“UP”鍵向右移動……除非單元格位于最后一個“新”行……在這種情況下,我們只想發送“Tab”鍵向右移動,不發送“UP”鍵。因此,我們檢查該行是否不是“新”行,然后我們發送額外的“UP”鍵。
如果CurrentCell當用戶按下回車鍵時網格列索引是最后一列,那么網格的選擇將移動“向下”,因此我們只需發送“HOME”鍵即可將選擇移動到該行的第一個單元格......除非選擇已經在最后一個“新”行上。在這種情況下,我們必須做出決定,我們可以將選擇移動到左上角,或者什么都不做,或者添加一個新行。在這種情況下,代碼會添加一個新行,因為我認為這是您想要的。
因此,我們再次檢查該行是否是最后一個“新”行,如果是,我們將新行添加到網格中。添加行后,我們發送“HOME”鍵將選擇設定為“新”行中的第一個單元格。
我們將能夠使用幾個網格事件在幾個地方使用這個方法。下面是我們將使用的網格事件以及為什么需要使用它們的簡要總結。
首先是 GRID 的“KeyDown”事件。此事件專門用于當單元格未處于“編輯模式”并且用戶按下“Enter”鍵時。
Private Sub DgvGrid_KeyDown(sender As Object, e As KeyEventArgs) Handles DgvGrid.KeyDown
If e.KeyCode = Keys.Enter Then
MoveGridSelection()
Else
If e.Shift AndAlso e.KeyCode = Keys.Delete Then
DeleteCurrentRow()
End If
End If
End Sub
接下來,我們需要捕捉按下“Enter”鍵并且單元格處于“編輯模式”的時間。我相信你已經知道了……KeyDown當用戶“編輯”一個單元格時,grids 事件不會觸發,這是有道理的,因為網格的編輯器正在捕獲單元格的鍵。
通常,我們會使用 gridsEditingControlShowing事件來提供幫助。當它觸發時,一個單元格將進入“編輯模式”。我們可以將網格單元轉換為泛型TextBox,然后訂閱該文本框KeyDown事件。這就是阻止用戶在數字單元格中輸入字母字符的方法。不幸的是,即使在這種情況下,KeyDown如果按下“Enter”鍵,事件也不會觸發。幸運的是,TextBoxes PreviewKeyDown按下“Enter”鍵時會觸發該事件。
EditingControlShowing所以,當單元格進入“編輯模式”時,我們需要 grids事件來連接這個事件。為了提供幫助,我們將創建一個TextBox名為的全域變數EditedCell,當單元格進入“編輯模式”時,我們將該單元格轉換為全域文本框,連接文本框PreviewKeyDown事件,然后等待用戶按下“Enter”鍵. 它可能看起來像……
Private WithEvents EditedCell As TextBox = Nothing
Private Sub DgvGrid_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DgvGrid.EditingControlShowing
EditedCell = CType(e.Control, TextBox)
RemoveHandler EditedCell.PreviewKeyDown, AddressOf EditedCell_PreviewKeyDown
AddHandler EditedCell.PreviewKeyDown, AddressOf EditedCell_PreviewKeyDown
End Sub
接下來,我們需要實作這個EditedCell_PreviewKeyDown事件。像 gridsKeyDown事件一樣,我們只需要檢查是否按下了“Enter”鍵,如果是,那么我們呼叫之前的方法來移動選擇。此外,由于用戶按下“Enter”鍵,我們也知道單元格將結束其編輯模式,因此我們不再需要全域文本框或其事件。因此,我們取消連接事件并將文本框設定為null. 如果我們不這樣做,那么事件可能會意外觸發。
Private Sub EditedCell_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles EditedCell.PreviewKeyDown
If (e.KeyCode.Equals(Keys.Enter)) Then
MoveGridSelection()
RemoveHandler EditedCell.PreviewKeyDown, AddressOf EditedCell_PreviewKeyDown
EditedCell = Nothing
Else
If e.Shift AndAlso e.KeyCode = Keys.Delete Then
DeleteCurrentRow()
End If
End If
End Sub
這應該是我們需要讓選擇向右移動而不是向下移動。
如果按下 Shift-Del 鍵,一些缺失的代碼會洗掉選定的行。
Private Sub DeleteCurrentRow()
If DgvGrid.SelectedCells.Count > 0 Then
If Not DgvGrid.CurrentCell.RowIndex = DgvGrid.NewRowIndex Then
DgvGrid.Rows.RemoveAt(DgvGrid.CurrentCell.RowIndex)
End If
End If
End Sub
最后,我對此進行了測驗,但是,我相信我可能遺漏了一些明顯的東西。所以請告訴我。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/490841.html
