.NET Framework - Vb.net Newbie looping problem

Asked By Rob W
20-Nov-09 02:34 PM
Greetings,

I have the functionality upon a button press to loop around the rows in the
datagrid view and where the checkbox is true then delete the row (see code
below).

It never deletes all those marked and when I use debug via printing
statements within the loop it randomly seems to skip a row.
I am not sure if this is because I remove a row from the datagridview
datasource and thus the datagridviewrow count has now changed.
Line tracing shows entering RowValidating/RowValidation but I did not see
anything strange happening there to impact the looping.

I do not delete via dataAdaptor as the datagridview does not map onto a
single table directly, instead I call bookingDeletion function form a class
which executes a delete SQL statement.

Can anyone please suggest why it does not loop through every single
datagridviewrow in the datagridview?


The looping code is below:-
The full code can be seen here:- http://pastebin.com/m3469f2a


'Loop around each row in datagridview

For Each booking As DataGridViewRow In DataGridView1.Rows

'Is cell value of selected is TRUE and name the same as login

If (booking.Cells("name").Value.Equals(bookersName) AndAlso
booking.Cells("selectColumn").Value = "True") Then

'Remove from database

Dim deleteBooking As New bookingsSession

If deleteBooking.bookingDeletion(cboRoom.SelectedValue,
booking.Cells("bookDate").Value, _

booking.Cells("startTime").Value, booking.Cells("endTime").Value) = True
Then

'Remove booking from datagridview

'DataGridView1.Rows.Remove(booking)

bookingsdata.Tables("bookings").Rows.Remove(DirectCast(booking.DataBoundItem,
DataRowView).Row)

bookingsdata.Tables("bookings").AcceptChanges()

End If

ElseIf (Not booking.Cells("name").Value.Equals(bookersName) AndAlso
booking.Cells("selectColumn").Value = "True") Then

'Highlight which bookings cannot be removed as not made by the user

MessageBox.Show("Warning: You are unable to delete the booking made on " _

& "the " & DirectCast(booking.Cells("bookDate").Value, DateTime).Date _

& " at " & CType(booking.Cells("starttime").Value,
DateTime).ToString("HH:mm") _

& " to " & CType(booking.Cells("endtime").Value, DateTime).ToString("HH:mm")
_

& " as booking was made by someone else.", "Warning: Unable to cancel
booking", _

MessageBoxButtons.OK)

booking.Cells("selectColumn").Value = "False"

End If

Next 'Retrieve next datgridviewrow for expection



Thanks
Rob
SqlDataReader
(1)
DataRowView
(1)
DeleteRows.Clear
(1)
DataTable
(1)
DateTime
(1)
AcceptChanges
(1)
DeleteRows
(1)
Tables
(1)
  Captain Jack replied to Rob W
20-Nov-09 02:50 PM
it is usually a bad idea to delete from any list or array that you are also
looping through. Just to be safe, I normally build a list of rows to delete,
then delete them in a separate loop, something like this:

Dim DeleteRows As New List(Of DataGridViewRow)
For Each Row As DataGridViewRow In grdMain.Rows
If <ROW SHOULD BE DELETED> Then
DeleteRows.Add(Row)
End If
Next
For Each Row As DataGridViewRow In DeleteRows
grdMain.Rows.Remove(Row)
Next
DeleteRows.Clear()

There may be better ways to do that, but that seems pretty safe, and I like
safe. :-)

--
Jack
  Mythran replied to Captain Jack
20-Nov-09 04:15 PM
If you reverse the direction the loop is iterating through, it would be fine
to delete form the list.  This involves not using For Each, but rather just
For.

For i As Integer = grdMain.Rows.Count - 1 To 0 Step -1
If {check here}
grdMain.Rows.Remove(i)
End If
Next I

HTH ;)

Mythran
  Captain Jack replied to Mythran
20-Nov-09 05:00 PM
I think I am poisoned by having problems with that in another programming
language, long ago, and I am something of a slave to "For Each".

I think thie the DataGridView, you would  have to do
grdMain.Rows.Remove(grdMain.Rows(i)). IIRC, the Remove method only takes a
row instance as an  argument.

--
Jack
  Rob W replied to Captain Jack
21-Nov-09 11:44 AM
Thanks for the replies, it is now dawned on me where the problem lies.

My datagridview is created MANUALLY and then assigned to a datatable with
all but TWO of the column are assigned values via .DataPropertyName

When im removing the datarow from the datatable updating the datagridview it
removes the datagridview checkbox column values which is not bound to the
datatable, what options do I have to avoid this?

The most striking one would to be include the selection checkbox/boolean
into the datatable, any other options?

Thanks
Rob
  Captain Jack replied to Rob W
23-Nov-09 10:25 AM
I am not sure about that one... I have only ever use the DataGridView control
as either completely bound to a DataTable, or completely manually creating
the rows. Lately, I have stuck to manually creating the rows, usually from a
SqlDataReader. I find that it loads a tiny bit faster and I get a little bit
better memory usage that way (for some reason, DataTable seems to take a
while to get garbage collected) and then I have got more freedom to work with
individual rows in the grid. That works pretty well for me, because I do not
have any code that lets users do edits in the grid itself; when a user needs
to edit a row, I pop up a window with editing controls, then I change the
row when the window exits.

I do have one situation where I let the user click multiple check boxes in a
grid, then I do an update on those rows and remove them. I use the technique
I described above, though; I scan the grid, copy the rows to be updated to a
temporary list, do the update, use the temp list to remove the rows, then
clear the list out.

--
Jack
Create New Account
help
DATETIME to only return DATE .NET Framework What magic to I need to do to get the DATETIME.Today to only return the DATE?!? C# Discussions ToShortDateString (1) ToLongDateString (1) TimeSpan (1) DateTime (1) Class (1) Date (1) String Felix Palmen (1) Felix Felix Palmen (1) Do you mean the "System.DateTime" struct? There is no such type as For System.DateTime, it is not possible for it "to only return the date". Note the name of the type: "DateTime". it is a date _and_ a time. Always. If you want to only _display_ the date after you have retrieved a particular DateTime value (including DateTime.Today), then just do that. There is nothing forcing you to include the time in
DateTime.MinValue.Year gives 2001 when parsed? .NET Framework Hello, I tried the following: String dts = String.Format("{0}-{1}-{2}", DateTime.MinValue.Day, DateTime.MinValue.Month, DateTime.MinValue.Year); DateTime dt = DateTime.Parse(dts); dts becomes "1-1-1" but dt becomes "01-01-2001". Shouldn't the minimum year be "0001" which is what I get when i do DateTime dt = new DateTime(); Thanks, Miguel C# Discussions Exception (1) DateTime (1) Decimal (1) Class (1) ParseExact (1) Console
me use less memory! .NET Framework I have got a problem. I load a huge datatable, with 111 columns. This datatable runs a System.OutOfMemory exception if its bigger than about 280, 000 rows. that is fine. I have come to accept that. when I fill a datatable up to near its max limit of 280k rows, use of program memory goes from choice there. but then I go through a loop like this: / / dtResults is the HUGE datatable. / / I clone the datatable a few times. this makes new datatables / / with the same columns. DataTable dtRejectedResults = new DataTable(); dtRejectedResults = dtResults.Clone(); DataTable dtExcludedResults = new DataTable(); dtExcludedResults = dtResults.Clone(); DataTable dtExcludedResults2 = new DataTable(); dtExcludedResults2 = dtResults.Clone(); DataTable dtExcludedResults3
realized it is probably not safe. Can someone comment on this: public DataRow GetWhatever() { using (DataTable dataTable = GetDataTable()) { return dataTable[0]; } } The problem is that "DataRow" has a "Table" property that points back to the same "dataTable" in the "using" statement above. That object is disposed of in the "using" statement however this correct? Note BTW that the indexer above is actually present in my case (the "DataTable" is actually a "DataTable" derivative created using the VS dataset designer) C# Discussions Visual Studio (1) Vista (1) DataTable.Dispose (1) Console.WriteLine (1) GetDataTable (1) DataTable (1) DataRow (1) ADO.NET (1) Yes, you definitely do not want to dispose objects
Need help understanding this code (sqlDataReader) .NET Framework I am trying to understand the code below. It takes an sqlDataReader and reads some fields off it. But I do not get why he is incrementing incremented i without being in a loop. Thanks, Tony C. public SomeFunction(System.Data.SqlClient.SqlDataReader sqlDataReader) { int i = 0; if(sqlDataReader.IsDBNull(i)) i++; else DisTolExportCompanyID = sqlDataReader.GetInt32(i++); if(sqlDataReader.IsDBNull(i)) i++; else BillToOCN = sqlDataReader.GetString(i++); if(sqlDataReader.IsDBNull(i)) i++; else BillToExchange = sqlDataReader.GetString(i++); if(sqlDataReader.IsDBNull