copy the data from unbound dgv to bound dgv - vb.net

I have two dgv, the first dgv is unbound and the second is bound. I want to copy the data in every cell to the bound dgv in order to save it. I have button but when I click it it says "Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound."
Here is my code:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
For i As Integer = 0 To DataGridView1.Rows.Count() - 1 Step +1
Dim rowAlreadyExist As Boolean = False
Dim check As Boolean = DataGridView1.Rows(i).Cells(3).Value
Dim row As DataGridViewRow = DataGridView1.Rows(i)
If check = True Then
If Sales.SalesDataGridView.Rows.Count() > 0 Then
For j As Integer = 0 To Sales.SalesDataGridView.Rows.Count() - 1 Step +1
If row.Cells(0).Value.ToString() = Sales.SalesDataGridView.Rows(j).Cells(0).ToString() Then
rowAlreadyExist = True
Exit For
End If
Next
If rowAlreadyExist = False Then
Sales.SalesDataGridView.Rows.Add(row.Cells(0).Value.ToString(),
row.Cells(1).Value.ToString(),
row.Cells(2).Value.ToString(),
row.Cells(3).Value.ToString(),
row.Cells(4).Value)
End If
Else
Sales.SalesDataGridView.Rows.Add(row.Cells(0).Value.ToString(),
row.Cells(1).Value.ToString(),
row.Cells(2).Value.ToString(),
row.Cells(3).Value.ToString(),
row.Cells(4).Value)
End If
End If
Next

Related

ComboBox Control within DatagridView

I want to use DGV as a table to take User’s inputs. And in few columns, I want User to select values from a collection hence I decided to use Comboboxcontrol. I selected a standard DGV ("DGV2") and a standard Combobox ("CBTest") as tools. And I programmed this Combo to appear on Columnindex 2 (when user enters the particular cell, Combo box pops-up). User can select from the combo items (Drop-Down-List) and after selection clicked done, curser moves to next column.
Now there is problems with UP/DOWN Keys when control is in cell having COMBO-BOX-
I am not able to control behavior of UP /DOWN Keys when user enters the Cell having COMBO Control.
Sometime with up-down keys cursor moves between Combobox items and sometimes it jumps in other rows.
I am a beginner so any hint and help will be useful.
Code I used -
Public Class frmSIDDGV
Dim nCol As Integer = 0
Dim nRow As Integer = 0
Private Sub frmSIDDGV_Load(sender As Object, e As EventArgs) Handles MyBase.Load
With DGV2
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.AutoResizeColumns()
.RowTemplate.Height = 40
.RowHeadersVisible = False
End With
DGV2.ColumnCount = 5
With DGV2
.Columns(0).Name = "Item"
.Columns(1).Name = "MRP"
.Columns(2).Name = "Qty"
.Columns(3).Name = "Unit"
.Columns(4).Name = "Amount"
End With
DGV2.Rows.Add()
DGV2(0, 0).Value = 1
End Sub
Private Sub DGV2_KeyUp(sender As Object, e As KeyEventArgs) Handles DGV2.KeyUp
If e.KeyCode = Keys.Enter Then
If ActiveControl.Name <> "CBTest" Then
If nCol = DGV2.ColumnCount - 1 Then
DGV2.Rows.Add()
DGV2.CurrentCell = DGV2(0, nRow + 1)
Else
DGV2.CurrentCell = DGV2(nCol + 1, nRow)
End If
End If
ElseIf e.KeyCode = Keys.Escape Then
If ActiveControl.Name = "CBTest" Then
CBTest.SelectedIndex = 0 : CBTest.Visible = False
DGV2.CurrentCell = DGV2(nCol, nRow)
DGV2.Focus()
End If
End If
End Sub
Private Sub DGV2_CurrentCellChanged(sender As Object, e As EventArgs) Handles DGV2.CurrentCellChanged
Try
nCol = DGV2.CurrentCell.ColumnIndex
nRow = DGV2.CurrentCell.RowIndex
Catch ex As Exception
nCol = 0
nRow = 0
End Try
End Sub
Private Sub DGV2_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DGV2.CellEnter
Select Case e.ColumnIndex
Case 2 ' User entered in Cell name "Item"
DGV2.Controls.Add(CBTest)
'DGV2.BeginEdit(True)
Dim oRectangle = DGV2.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
CBTest.Size = New Size(oRectangle.Width, oRectangle.Height)
CBTest.Location = New Point(oRectangle.X, oRectangle.Y)
CBTest.Visible = True
SendKeys.Send("{F4}")
CBTest.SelectedIndex = 0
CBTest.Capture = True
CBTest.Focus()
End Select
End Sub
Private Sub CBTest_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles CBTest.SelectionChangeCommitted
With DGV2
.Focus()
.Item(nCol, nRow).Value = Trim(CBTest.Text)
.CurrentCell = .Rows(.CurrentRow.Index).Cells(nCol + 1)
End With
CBTest.Visible = False
End Sub
End Class

Select only one checkbox from multiple checkbox in a row from DataGridView

I'm using DataGridView with DataSource from TableAdapter and add 5 unbound columns with type DataGridViewCheckBoxColumn .
They are : "lima","empat","tiga","dua","satu"
What I need to do, in the same row when checkbox "lima" is selected, the rest checkboxes become unselected or only can select one checkbox in the same row
Here's what I wrote down in CellValueChanged event :
Private Sub DataGridView3_CellValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView3.CellValueChanged
If DataGridView3.CurrentRow IsNot Nothing Then
Dim SelectedColumnName = DataGridView3.Columns(DataGridView3.CurrentCellValue.ColumnIndex).Name
If e.ColumnIndex = DataGridView3.Columns("lima").Index OrElse _
e.ColumnIndex = DataGridView3.Columns("empat").Index OrElse _
e.ColumnIndex = DataGridView3.Columns("tiga").Index OrElse _
e.ColumnIndex = DataGridView3.Columns("dua").Index OrElse _
e.ColumnIndex = DataGridView3.Columns("satu").Index Then
Dim Row = CType((CType(DataGridView3.DataSource.Current, DataRowView)).Row, DataRow)
If SelectedColumnName = "lima" Then
If DataGridView3.CurrentRowCellValue("lima") = "True" Then
Row.Item("empat") = False
Row.Item("tiga") = False
Row.Item("dua") = False
Row.Item("satu") = False
End If
'and so..on
ElseIf SelectedColumnName = "satu" Then
If DataGridView3.CurrentRowCellValue("satu") = "True" Then
Row.Item("lima") = False
Row.Item("empat") = False
Row.Item("tiga") = False
Row.Item("dua") = False
End If
End If
DataGridView3.CurrentCell = DataGridView3(e.ColumnIndex, e.RowIndex)
End If
End If
End Sub
And this is the functions for CurrentCell and CurrentRowCellValue in module
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Function CurrentRowCellValue(ByVal sender As DataGridView, ByVal ColumnName As String) As String
Dim Result As String = ""
If Not sender.Rows(sender.CurrentRow.Index).Cells(ColumnName).Value Is Nothing Then
Result = sender.Rows(sender.CurrentRow.Index).Cells(ColumnName).Value.ToString
End If
Return Result
End Function
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Function CurrentCellValue(ByVal sender As DataGridView) As DataGridViewCell
Return sender(sender.Columns(sender.CurrentCell.ColumnIndex).Index, sender.CurrentRow.Index)
End Function
and this is from CurrentCellDirtyStateChanged event
Private Sub DataGridView3_CurrentCellDirtyStateChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView3.CurrentCellDirtyStateChanged
If TypeOf DataGridView3.CurrentCell Is DataGridViewCheckBoxCell Then
DataGridView3.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
I already set the DataGridView's ReadOnly property to False. The problem is that I still can check all the checkboxes in the same row.
Can someone give advice of what I did wrong here ?
Thanks
Some tips:
See this link concerning CellValuechanged event when working with checkBoxs
If they are unbound columns, you can't change values via the DataSource.Current row: table has no definition for lima, empat, ...
This workaround (using CellContentClick) works for me (no need to extension methods and CurrentCellDirtyStateChanged event):
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView3.CellContentClick
Dim checkboxIndexes As New List(Of Integer)
checkboxIndexes.Add(DataGridView3.Columns("lima").Index)
checkboxIndexes.Add(DataGridView3.Columns("empat").Index)
checkboxIndexes.Add(DataGridView3.Columns("tiga").Index)
checkboxIndexes.Add(DataGridView3.Columns("dua").Index)
checkboxIndexes.Add(DataGridView3.Columns("satu").Index)
If checkboxIndexes.Contains(e.ColumnIndex) Then
'check for false value because event occurs before row is validated
If DataGridView3.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False Then
For Each index In checkboxIndexes
If index <> e.ColumnIndex Then
DataGridView3.Rows(e.RowIndex).Cells(index).Value = False
End If
Next
End If
End If
End Sub
I made an improve to the code added before in order to achieve my goals of checking checkboxes of the same row in different columns. It works for me.
Private Sub Grilla_CellClick(sender As Object, e As Telerik.WinControls.UI.GridViewCellEventArgs) Handles Grilla.CellClick
Dim checkboxIndexes As New List(Of Integer)
checkboxIndexes.Add(Grilla.Columns("Select").Index)
checkboxIndexes.Add(Grilla.Columns("Select1").Index)
If checkboxIndexes.Contains(e.ColumnIndex) Then
'check for false value because event occurs before row is validated
If Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False Then
For Each index In checkboxIndexes
If index <> e.ColumnIndex Then
'Do nothing here
Else
If Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False Then
Grilla.Rows(e.RowIndex).Cells(index).Value = True
Else
Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False
End If
End If
Next
Else
If Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = True Then
For Each index In checkboxIndexes
If index <> e.ColumnIndex Then
'Do nothing here
Else
If Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False Then
Grilla.Rows(e.RowIndex).Cells(index).Value = True
Else
Grilla.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False
End If
End If
Next
End If
End If
End If
Grilla.TableElement.Update(GridUINotifyAction.DataChanged)
End Sub

Can someone tell what's wrong with that code?

this button is to check if there is an empty cells in the last row .
if there is filled cell the button (confirmer) will be enabled .. the application crashes when i debug
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
DataGridView1.AllowUserToAddRows = "true"
DataGridView1.ClearSelection()
DataGridView1.Rows(DataGridView1.NewRowIndex).Selected = True
Dim c As Boolean
Dim D As String
Dim nbrcell As Integer = DataGridView1.CurrentRow.Cells.Count - 1
c = Confirmer.Enabled
Do
For i As Integer = 0 To nbrcell - 1
D = DataGridView1.SelectedRows(0).Cells(i).Value
If D <> "" Then
c = True
End If
Next
Loop Until c = True
End Sub
I have changed your code like this:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
DataGridView1.AllowUserToAddRows = "true"
DataGridView1.ClearSelection()
DataGridView1.Rows(DataGridView1.NewRowIndex).Selected = True
Dim c As Boolean
Dim D As Object
Dim nbrcell As Integer = DataGridView1.CurrentRow.Cells.Count - 1
c = Confirmer.Enabled
Do
For i As Integer = 0 To nbrcell - 1
D = DataGridView1.SelectedRows(0).Cells(i).Value
If Not IsDBNull(D) Then
c = True
End If
Next
Loop Until c = True
End Sub
Hope it helps
You are trying to read the number of cells from the CurrentRow property.
But if there is no CurrentRow set when you run this code then the code crashes with a Null Reference Exception. (A.K.A. Object Reference not set to an instance of an object)
Instead you should use the row at NewRowIndex.
Dim nbrcell As Integer = DataGridView1.Rows(DataGridView1.NewRowIndex).Cells.Count
and don't subtract 1 from the count of cells. You are doing this two times. One when you get the Count and one more time when you loop over that count (So the last cell is not checked)
Now the loop: You never exit from that loop if the cells are all filled
Dim D as Object
Dim allFilled = True
For i As Integer = 0 To nbrcell - 1
D = DataGridView1.SelectedRows(0).Cells(i).Value
If D Is Nothing OrElse
Convert.IsDBNull(D) OrElse
String.IsNullOrWitheSpace(D.ToString()) Then
allFilled = False
Exit For ' no need to continue the loop
End If
Next
Confirmer.Enabled = allFilled
I have removed the external while, the the loop is executed only using the for and it is stopped as soon as a cell with Nothing, DBNull or empty string value is found. At that point a boolean variable is set to false and applied to the Enabled property of the button. If no cells are found to be invalid then the boolen variable remains set to true and the button will be enabled.
Probably it is possible to change something in the evaluation code of the cell, but this depends on how do you fill the grid (manually or through a database data)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Confirmer.Visible = True
Confirmer.Enabled = False
DataGridView1.AllowUserToAddRows = "true"
DataGridView1.ClearSelection()
DataGridView1.Rows(DataGridView1.NewRowIndex).Selected = True
Dim c As Boolean = False
Dim D As Object
Dim nbrcell As Integer = DataGridView1.CurrentRow.Cells.Count
Do
For i As Integer = 0 To nbrcell - 1
D = DataGridView1.Rows(DataGridView1.NewRowIndex).Cells(i).Value
If Not IsDBNull(D) Then
Confirmer.Enabled = True
c = True
End If
Next
Loop Until c = True
End Sub
The Problem now is that the button(confirmer) is always enabled even is the cell is empty

Displaying number of rows checked/unchecked on datagridview

I have a datagrid on a form with a checkbox to select all records. Column (0) of my datagrid is a checkbox column, and on the header I put a checkbox to select all records and display the number of records selected. Here is my code:
Private Sub chkSelectRecords_CheckedChanged(sender As Object, e As EventArgs) Handles chkSelectRecords.CheckedChanged
'Procedure runs when the checkSelectRecords is clicked.
'The loop selects all records on the datagrid when checked
'and clears selection when unchecked.
Dim chkRow As Integer = 0
If chkSelectRecords.Checked = True Then
For Each row As DataGridViewRow In grdDeleteRecord.Rows
row.Cells(0).Value = (row.Cells(0).Value IsNot DBNull.Value)
chkRow += 1
lblRowCount.Visible = True
lblRowCount.Text = chkRow.ToString & " Record(s) Selected"
Next
Else
For Each row As DataGridViewRow In grdDeleteRecord.Rows
row.Cells(0).Value = (row.Cells(0).Value Is DBNull.Value)
chkRow += 0
lblRowCount.Text = chkRow.ToString & " Record(s) Selected"
Next
End If
End Sub
I placed another procedure when the user selects one record at a time:
Private Sub grdDeleteRecord_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles grdDeleteRecord.CellContentClick
' Shows how to get count of checked or unchecked checkbox column count along with
' how to get column data back for checked items.
Dim chkRowCount As Integer = 0
grdDeleteRecord.EndEdit()
For Each row As DataGridViewRow In grdDeleteRecord.Rows
If row.Cells(0).Value = True Then
chkRowCount += 1
Else
chkRowCount += 0
lblRowCount.Visible = True
lblRowCount.Text = chkRowCount.ToString & " Record(s) Selected"
End If
Next
End Sub
Both procedures work as needed. The problem is when I select all records my label does not update the number of records that are now selected. I am sure this is happening because they are two separate events, I just don't know how to link the events or write a procedure that accomplishes all three tasks
Here's a function I wrote for you. You must use the CellValueChangedEvent and the CurrentCellDirtyStateChanged events...
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblRowCount.Text = SetLabel()
End Sub
Private Function SetLabel() As String
Dim strRows As String = String.Empty
Dim intRows As Integer = 0
For i As Integer = 0 To grdDeleteRecord.Rows.Count - 1
If CBool(grdDeleteRecord(0, i).Value) Then
intRows += 1
End If
Next
If intRows > 0 Then
strRows = intRows.ToString & " Record(s) Selected"
lblRowCount.Visible = True
End If
Return strRows
End Function
Private Sub grdDeleteRecord_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles grdDeleteRecord.CellValueChanged
lblRowCount.Text = SetLabel()
End Sub
Private Sub grdDeleteRecord_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles grdDeleteRecord.CurrentCellDirtyStateChanged
If grdDeleteRecord.IsCurrentCellDirty Then
grdDeleteRecord.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
When you check or uncheck these checkboxes it will trigger this event and thus update your label. Then you can use this where ever you need it to be used.

Change editted cell in datagridview on enter (vb.net)

I have a datagridview table that is populated by using a datatable as a datasource. The datagridview has been set to edittable and I can change the values of cells but of course, the changes do not reflect in the original database table since the grid view is not directly bound. Is it possible to have the datagridview in such a way that when I press enter (when editting a cell), the focus shifts to the cell on the right (rather then selecting the row below)? This would need to keep on going until I reach the right most column, in which case the following edit cell would be the first cell in the following row.
Thanks in advance!
Try this:
define a flag flag_edited that will be raised when an edit occurs (CellEndEdit event)
define a function changeSelectionToNextCell that will undo default behavior's selection change (SelectionChanged event)
Here is a sample:
Private flag_edited As Boolean
Private Sub DataGridView1_CellEndEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
flag_edited = True
End Sub
Private Sub DataGridView1_SelectionChanged(sender As Object, e As System.EventArgs) Handles DataGridView1.SelectionChanged
changeSelectionToNextCell()
End Sub
Private Sub changeSelectionToNextCell()
If flag_edited Then
flag_edited = False
If DataGridView1.CurrentCell IsNot Nothing Then
Dim row_index As Integer = DataGridView1.CurrentCell.RowIndex - 1
Dim col_index As Integer = DataGridView1.CurrentCell.ColumnIndex + 1
If col_index = DataGridView1.ColumnCount Then
col_index = 0
row_index += 1
End If
DataGridView1.CurrentCell = DataGridView1.Rows(row_index).Cells(col_index)
End If
End If
End Sub