DataTable.DefaultView.Find doesn't

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi

After creating a NewRow and Adding it to a DataTable, it receives it's
autoincrement ID of -1.

If I try to find it by DataTable.DefaultView.Find(-1), it returns 0, which
is incorrect since it is actually at the end of the table (over 1000 records)
and is verified by
DataTable.Rows(DataTable.Rows.Count-1).Item("ID") returns -1

Any ideas as to why this is not working?
 
Hi Terry,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you're using a DataView to find a
certain row but returned incorrect index of the row. If there is any
misunderstanding, please feel free to let me know.

As far as I know, the DataView.Find method searches for the value on the
sorted column. So could you please check if the default column is sorted
on the autoincrement column. If the autoincrement field is the primary key
of the table, you can also try to use DataTable.Rows.Find method to get the
row's reference.

Please check the following links for more information.

http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatadataviewcl
assfindtopic.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemdatadatarowcollectionclassfindtopic.asp

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi Kevin

Yes, I have the sort property set to the autoincrement column.

I need to find the position in the datatable of the added row. It is
currently at the end. Could this be because it is negative? and all other IDs
are 0 or positive?

The alternative approach you mentioned returns the correct row, but this
does't tell me which position it is in.
 
Hi Kevin

I have established that the problem is being caused by the added row being
at the end of the datatable, but being found at the start of the dataview,
since the dataview requires a sort order.

Trouble is, all the controls are bound to the datatable, and it's position
controlled by the currencymanager, neither of which are anything to do with
the dataview.

So should I be using the DataView for everything?
 
Hi Terry,

This is the designed behavior of the DataGrid. The DataGrid is actually
binding to the default data view of the DataTable. So the index returned
from DataView.Find and CurrencyManager is the position in the DataView. I
know that the position of the new row in the RowCollection is the last, but
in the DataView, it's the first one.

If you can let me know what you're trying to do with the row index, maybe I
can find a workaround for you.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi Kevin

Thanks for the reply.

I have a Form1 containing a ReadOnly sortable DataGrid and Add, Modify and
Delete buttons. I also have a strongly typed dataset containing a master
tAddressBook table and a child tAddressBookContact table, both with
autoincrement = True, autoincrementseed & step = -1. A one-many Relationship
exists with UpdateRule and DeleteRule as cascade.

The selected row in the datagrid is obtained by:
-----------------------------------------------------------------------------
Dim bm As BindingManagerBase =
Me.dgAddressBook.BindingContext(Me.dgAddressBook.DataSource,
Me.dgAddressBook.DataMember)
Dim dr As DataRow = CType(bm.Current, DataRowView).Row
intpkID = dr.item("AddressBookID")
-----------------------------------------------------------------------------

Clicking the Delete simply deletes the selected record (except there is a
bug in the datagrid for deleting last row for ReadOnly datagrid, but that's
another post!).

The Modify button launches a Form2. I give Form2 a new property DataSource
and set it to the Dataset, and also a new property AddressBookID and set it
to the intpkID above. Form2 then needs to find this again (because the order
of the datatable, does not match the sorted grid) and does so successfully
whether the datagrid is sorted or not using:
-----------------------------------------------------------------------------
Me.mcmAddressBook = Me.BindingContext(Me.DataSource, "tAddressBook")
Me.DataSource.tAddressBook.DefaultView.Sort = "AddressBookID ASC"
Me.mcmAddressBook.Position =
Me.DataSource.tAddressBook.DefaultView.Find(Me.AddressBookID)
-----------------------------------------------------------------------------
where mcmAddressBook is a form level CurrencyManager.

The Add button first adds a new strongly typed datarow to the datatable:
-----------------------------------------------------------------------------
Dim drAddressBook As dsAddressBook.tAddressBookRow
drAddressBook = Me.DsAddressBook1.tAddressBook.NewRow()
Me.DsAddressBook1.tAddressBook.Rows.Add(drAddressBook)
intpkID = drAddressBook.item("AddressBookID")
-----------------------------------------------------------------------------
It then launches a Form2. I then pass the Dataset and AddressBookID as with
the Modify. Form2 then needs to find the AddressBookID again using:
-----------------------------------------------------------------------------
Me.mcmAddressBook = Me.BindingContext(Me.DataSource, "tAddressBook")
Me.DataSource.tAddressBook.DefaultView.Sort = "AddressBookID ASC"
Me.mcmAddressBook.Position =
Me.DataSource.tAddressBook.DefaultView.Find(Me.AddressBookID)
-----------------------------------------------------------------------------
This finds it in the first position because the autoincrement id of the
newly added row is -1 (all existing ids are 0 or positive). The actual row
exists in the last position of the datatable.

The DataSource of all controls in Form2 is the dataset passed in, i.e.
Me.DataSource.
The DataMember of all controls is a string comprising of the
DataTable.ColumnName.
There also exists on Form2 another datagrid that has the DataMember of
DataTable.Relation_AddressBook_AddressBookContact.

Maybe I need to bind to a DataView or something, but this all seems so much
more complicated than it needs to be.
At the moment, for the Add condition, as a work around I use:
-----------------------------------------------------------------------------
Me.mcmAddressBook.Position = Me.DataSource.tAddressBook.Rows.Count - 1
-----------------------------------------------------------------------------
which works but is extremly ropey.


BACKGROUND:
From other posts you have suggested passing in the DataRow and using
GetChildRows to populate the Form2 datagrid. This need the manual filling of
another table to bind to the grid for it to work correctly (i.e. not show
'HasRows' etc. columns), and because I will have many hierarchical forms in
the above format, I consider that this will be too much additional coding for
the simple operations that I want to conduct. I am therefore passing in the
Dataset and going from there.

Many Thanks
 
Hi Terry,

According to your description, I assume that you need to move the the
current position to the last row on the datagrid. Actually, to the
CurrencyManager, the newly added row is not the last row, but the first. So
if you still need to point to the last row, you need to use

Me.mcmAddressBook.Position = Me.DataSource.tAddressBook.DefaultView.Count -
1

Similar to your workaround, but more reliable using the DefaultView. This
is not ropey, but the common solution.

If you need to move the current position to the newly added row, just use

Me.mcmAddressBook.Position =
Me.DataSource.tAddressBook.DefaultView.Find(Me.AddressBookID)

You will get the DataRowView of the new row with mcmAddressBook.Current.
It's a DataRowView object and its Row property will bring you the reference
to DataRow object.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Thanks Kevin

Based on your hint about DataView reliability, I recoded the forms with a
new DataView and bound to those throughout. The problem no longer exists.

Many thanks
 
You're welcome, Terry.

Thanks for sharing your experience with all the people here. If you have
any questions, please feel free to post them in the community.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Back
Top