vb.net change value of a cell in a databound datagridview - vb.net

I have a datagridview that has been populated from a datatable using the datasource property. I need to change the value of a cell without affecting the database. So far I could only find that I have to first change the databound item but no information about how to do that. Besides, I don't want to change the databound item.
The reason for wanting to do this is that I have a list of records with a start and end time and there is a computed field that gives the difference in seconds. I need to change the value of the computed field and change the height of the row accordingly, that is, the height of each row is proportional to the duration it represents. Changes are done from a text box which increments quickly if the "increase" button is kept down and therefore I cannot change the database with each increment. Rather I would change the value in the table frequently and update the database once the increments stops.
I have tried updating the datagridview directly using this code:
dgvTasks.Rows(SelectedRowIndex).Cells(5).Value = DateAdd(DateInterval.Minute, DateDiff(DateInterval.Minute, CDate("00:00:00"), CDate(txtDuration.Text & ":00")), dgvTasks.Rows(SelectedRowIndex).Cells(4).Value)
But receive the error:
System.Data.ReadOnlyException: Column 'Column1' is read only.
I also tried updating the datatable, and allowing the calculated column to update:
dtblTasks.Rows(SelectedRowIndex)(5) = DateAdd(DateInterval.Minute, DateDiff(DateInterval.Minute, CDate("00:00:00"), CDate(txtDuration.Text & ":00")), dtblTasks.Rows(SelectedRowIndex)(4))
dgvTasks.DataSource = dtblTasks
But the calculated value doesn't change.
I am also providing an additional calculated value (in the SQL) where I find the difference in minutes and the append a string literal to that:
( CAST ( DATEDIFF(MINUTE, Tasks.TaskStart, Tasks.TaskEnd) AS NVARCHAR(10) ) + ' mins') AS TaskDurationString
Is there a way to detach the grid from the datasource but still keep the data visible in the datagrid and manipulate it (without affecting the databound object)? Or perhaps some other approach to this problem?

Updating the calculated column in the DataTable should work - I've just tried it, and both when I edit one of the values that are part of the calculated value, and when I change the value in code, that column is recalculated and the grid UI updates.
One thing to check is that you are calculating the value correctly. You should be using the DataTable~ column [Expression` property]1. Something like this:
dt.Columns["FullName"].Expression = "FirstName + LastName";
Since it appears that you don't actually need to bind any of these values to the DataTable or persist them to the database, one possible solution is to do all of this in an unbound DataGridView calculation column.
To do that add a column using the designer, then in the cell validating event have something like this:
void dataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.Rows[e.RowIndex].Cells["TargetColumn"].Value = dataGridView1.Rows[e.RowIndex].Cells["FirstName"].Value.ToString() + dataGridView1.Rows[e.RowIndex].Cells["LastName"].Value.ToString();
dataGridView1.Rows[e.RowIndex].Height = dataGridView1.Rows[e.RowIndex].Cells["LastName"].Value.ToString().Length + dataGridView1.Rows[e.RowIndex].Cells["FullName"].Value.ToString().Length;
}

Related

Question About Datagridview Format Styling

i want to Show Thousand Separator in Datagridview Column
So i added One Column in datagridview so i Run this code But It's not working with me
You need to explicitly specify the column's ValueType if you don't have a DataSource to bind (ex. DataTable) which is the source of the data types as well. Here, you need a column of a numeric type such as Decimal.
So, before you populate the grid or add new rows, do:
With DataGridView2.Columns(0)
.ValueType = GetType(Decimal)
.DefaultCellStyle.Format = "#,#.##"
End With
In case the control is bound to DataSource, make sure that the type of the data field/property in question is numeric.

Access VBA Combobox Store Value in Column

I have an MS ACCESS Combo Box and I wish to change the value of one of the columns in a particular row. I get error "object required" when I run this line:
Me.ComboName.Column(12, intUseRow) = myVar
(If I am unable to use the above syntax then you should also know that the row I am trying to change is always going to be the "current" visible row so there may be another way of solving the problem due to this fact).
Thanks!
If you have a recordset that is bound to a Table/Query, you will need to change the underlying data then requery the combobox to see changes.
If you load it manually (like in the form load event) and have the comboBox Row Source Type to "Value List" - you should be able to update it like this:
Copy all the data from the selected row into variables.
Combobox.RemoveItem (selected index)
change the required variable to the new value.
construct the semicolon separated string for the value list entry
combobox.AddItem new-string.
a bit messy, but it works correctly!

Value Retrieve from Datagridview's Columns

I am working on VB in Visual Studio 2010. And I've seen errors of greatness in which when I double click on a line of datagridview, I get the values of its columns in such a way.
Datagridview1.SelectedRows(0).Cells(1).Value
But the most surprising thing is that with this same code I get the values ​​of different columns each time without changing the index value in Cells(). I also put the name of the column inside the Cells(), but I did not get any value from this too.
Datagridview1.SelectedRows(0).Cells("name").Value
And the first column of this datagridview Cells(0) always returns the null value itself. I do not know how.
I have also used some column formating. like
With Datagridview1
.ColumnCount =2
.Columns(0).HeaderText ="Name"
.Columns(0).DataPropertyName = "pname"
.Columns(0).Width =100
.Column(1).HeaderText = "Son of"
.Column(1). DataPropertyName = "fname"
The big problem here is that it gives value to different columns each time with a single code
Is there any solution available for this?

Is there a way to allow only unique values in a column of an Infragistics UltraWinGrid?

I'm using an Infragistics UltraWinGrid with a column of drop-down boxes. I don't want the user to be able to select the same value for multiple rows in that column. Is there a simple (or heck, I'd settle for advanced) way to do this?
I'm using VB.NET
-EDIT-
I tried setting a filter on the data source for the drop-down box. But when I did that, the values in the other boxes in that column started disappearing (not the values themselves, but the descriptions that they were supposed to represent, so instead of reading "Information", it just said "1"). All of the cells in a column refer to the same combo box, so if you filter out a value from the data source for one of them, you filter it out for all of them.
I'm currently trying to catch a CellChange event and check against all other currently-used values. If it was already used, I would put up a message saying as much and revert back to the old value. However, the value comes back as the previously-saved one, so... not helpful. About to see if I can use the "text" property.
Since you're using Infragistics, you could use an UltraDropDown which is bound to a DataTable (or something similiar) which you can add a "Selected" column in addition to a column holding the values you want to show.
As each value is selected (via AfterCellUpdate or AfterCellListCloseUp for instance), you could update the "Selected" column in that data source and use a column filter to only show items which haven't been marked as selected. That way as items are selected or removed, the contents of the drop-down would be automatically updated.
To clear the selected flag from the old value, you can use the BeforeCellUpdate event to access the cell's current value then perform a lookup on the data source bound to the UltraDropDown using that value to clear the flag.
Solved it:
The trick was to use BeforeCellUpdate whose BeforeCellUpdateEventArgs has a "NewValue" and a "Cancel" member. I just look through all of the items in the column to see if any of them match the new value. If one does, I notify the user and cancel the operation.
And that's it. Here's the code:
Private Sub myUltraWinGrid_BeforeCellUpdate(ByVal sender As Object, ByVal e As Infragistics.Win.UltraWinGrid.BeforeCellUpdateEventArgs) Handles myUltraWinGrid.BeforeCellUpdate
If e.Cell.Column.Key = "myColumn" Then
Dim newValue As Integer = CInt(e.NewValue)
For Each row As Infragistics.Win.UltraWinGrid.UltraGridRow In myUltraWinGrid.Rows
If row.Cells("myColumn") IsNot e.Cell _ 'So I'm not checking against the current cell
AndAlso CInt(row.Cells("myColumn").Value) = newValue Then
MsgBox("That value has already been used in this column")
e.Cancel = True
End If
Next
End If
End Sub

figure out rowindex on a row I just inserted?

I've got a vb project I am updating and it has a datagridview, a panel, and buttons along the bottom. The buttons control CRUD operations. The panel shows numerical up/downs and textboxes to represent the selected row.
I use some logic to keep track of current selected row and current row index for timer updates in the background. Upon delete I reset focus on the first row. Upon loading I set focus on first row. On update I keep current row focus.
Upon a good insert I would like to set the focus to the row I just inserted. But I do not know a way to determine what the rowindex value is for this freshly inserted row. My datatable which the datagridview uses is sorted on two id columns so it's not like the new entry will just jump to the bottom.
Any ideas on how I can implement this?
If you don't want to deal with the RowAdded event as Jay Riggs suggested, if you add it using a row object, as opposed to just Rows.Add, you should be able to pull that off of the row object after it's inserted.
Dim dgr As New DataGridViewRow()
DataGridView1.Rows.Add(dgr)
Me.DataGridView1.Rows.IndexOf(dgr)
This should also work for insert as well.
Check out the DataGridView RowAdded event; its DataGridViewRowsAddedEventArgs parameter includes the RowIndex property which gives you what you need.
The event fires everytime a row is added, so you'll have to either wire the event up when you want to check for added rows, or ignore the event when you don't care when a row is added (such as when your grid fills with data).
If you manually add rows to the DataGridView, then you can just use the return value from the Add method. Examples:
Dim newRowIndex As Integer = myDataGridView.Rows.Add()
myDataGridView.Rows(newRowIndex).Selected = True
No need to call IndexOf. If the DataGridView is bound to a DataSource then Jay Riggs' solution of using the RowsAdded event is the way to go.