Moving CurrencyManager to specific row in Data Source

M

Mike Edenfield

I have a series of user-bound controls that are associated with a
dataset, and need to be able to move the displayed data row in one
control based on events in another.

I have all of the controls bound to the same dataset on my form, and the
navigation controls are passing a complete DataRow object in the event
arguments. I know I need to get the CurrencyManager for the binding
context, and set it's Position, but it's not working properly.

The code I am currently using follows (Names have been changed to
protect the innocent :). I have a strongly typed dataset called
"TypedDataSet" with a table called "Table" in it. The table has an "ID"
column which is the primary key. The data is being read into the
dataset from an XML document.

/**********/
TypedDataSet ds = _dataSet;
TypedDataSet.TableRow row = e.nodeData as TypedDataSet.TableRow;
int pos = ds.Table.DefaultView.Find(row.ID);

CurrencyManager cm = BindingContext[ds, "Table"] as CurrencyManager;
cm.Position = pos;
/**********/

When I run this code, the data-bound controls do move to a new row. But
it's always the wrong row. The problem appears to be that the DataView
has the rows sorted differently than the DataTable. I have tried
explicitly sorting by primary key (DefaultView.Sort = "ID ASC") as well
as using the default (DefaultView.ApplyDefaultSort = true), but the
results are identical.

The DataTable.Find() method doesn't appear to be useful, since that
returns a DataRow -- that I already have -- but I have no way to move
the CurrencyManager to a specific data row object, only to a specific
position.

I'm sure there's some .NET property or method I'm missing but I can't
seem to find it. Any ideas?

--Mike
's/not.//g' to email me.
 
W

W.G. Ryan eMVP

Mike:

The bindingManager's count property will always equal the table's rows count
whereas if the rowfilter is set on the dataview, it will probably have a
different count, hence they'll be out of sync.

One way I've handled this in the past is when I've loaded the datatable, I
created a HashTable based on the Original sort position of the table storing
the KeyValue and the original index in the table. So let's say row 1000 had
a Key Value of Ryan and it was position 999. I can always use the Keyvalue
to get the number 999 which is what I set the bindingmanagerbase to. The
scenario I had for navigation was navigation buttons and a Outlook style
Listbox on the side. This way regardless of the filtering that the listbox
had, I can always know what the next/prev/current value is and use that to
lookup what Index I want.

There is probably a more elegant solution but this was pretty
straightforward to implement and it works - and it allows me to filter
everything by any criteria and I can always find the correct position in the
binding.

HTH,

Bill

--
W.G. Ryan, MVP

www.tibasolutions.com | www.devbuzz.com | www.knowdotnet.com
Mike Edenfield said:
I have a series of user-bound controls that are associated with a
dataset, and need to be able to move the displayed data row in one
control based on events in another.

I have all of the controls bound to the same dataset on my form, and the
navigation controls are passing a complete DataRow object in the event
arguments. I know I need to get the CurrencyManager for the binding
context, and set it's Position, but it's not working properly.

The code I am currently using follows (Names have been changed to
protect the innocent :). I have a strongly typed dataset called
"TypedDataSet" with a table called "Table" in it. The table has an "ID"
column which is the primary key. The data is being read into the
dataset from an XML document.

/**********/
TypedDataSet ds = _dataSet;
TypedDataSet.TableRow row = e.nodeData as TypedDataSet.TableRow;
int pos = ds.Table.DefaultView.Find(row.ID);

CurrencyManager cm = BindingContext[ds, "Table"] as CurrencyManager;
cm.Position = pos;
/**********/

When I run this code, the data-bound controls do move to a new row. But
it's always the wrong row. The problem appears to be that the DataView
has the rows sorted differently than the DataTable. I have tried
explicitly sorting by primary key (DefaultView.Sort = "ID ASC") as well
as using the default (DefaultView.ApplyDefaultSort = true), but the
results are identical.

The DataTable.Find() method doesn't appear to be useful, since that
returns a DataRow -- that I already have -- but I have no way to move
the CurrencyManager to a specific data row object, only to a specific
position.

I'm sure there's some .NET property or method I'm missing but I can't
seem to find it. Any ideas?

--Mike
's/not.//g' to email me.
 
M

Mike Edenfield

W.G. Ryan eMVP said:
One way I've handled this in the past is when I've loaded the datatable, I
created a HashTable based on the Original sort position of the table storing
the KeyValue and the original index in the table. So let's say row 1000 had
a Key Value of Ryan and it was position 999. I can always use the Keyvalue
to get the number 999 which is what I set the bindingmanagerbase to.

This works for as well, I'm just distressed (a tiny bit) that there's no
easier way. It would be nice to have the CurrencyManager's DataView
object exposed (since it is clearly different from the default data view).

For the time being, I'm never expecting more than 10 records in any
given table, so I'm sticking with my brute-force for-loop solution.

Thanks for the help!

--Mike
 
S

Scave

/**********/
TypedDataSet ds = _dataSet;
TypedDataSet.TableRow row = e.nodeData as TypedDataSet.TableRow;
int pos = ds.Table.DefaultView.Find(row.ID);

CurrencyManager cm = BindingContext[ds, "Table"] as CurrencyManager;
cm.Position = pos;
/**********/

When I run this code, the data-bound controls do move to a new row. But
it's always the wrong row. The problem appears to be that the DataView
has the rows sorted differently than the DataTable. I have tried
explicitly sorting by primary key (DefaultView.Sort = "ID ASC") as well
as using the default (DefaultView.ApplyDefaultSort = true), but the
results are identical.

The DataTable.Find() method doesn't appear to be useful, since that
returns a DataRow -- that I already have -- but I have no way to move
the CurrencyManager to a specific data row object, only to a specific
position.


Try something like this instead.
/**********/
TypedDataSet ds = _dataSet;
TypedDataSet.TableRow row = e.nodeData as TypedDataSet.TableRow;
CurrencyManager cm = BindingContext[ds, "Table"] as CurrencyManager;

DataView tableView = (DataView)cm.List;
int pos = tableView.Find(row.ID);
cm.Position = pos;
/**********/

The problem in your code (as you suggested) was that you were finding
a position in one DataView (the DataTable's default) and then trying
to map it to another completely different DataView. The code above
just replaces the default view you used with one obtained from the
CurrencyManager of interest.

Keep in mind that the Find method requires a sort order to be set.
What I do is reference the view in my initialisation like:
DataView myView = (DataView)myCM.List;

Then I'll apply the default sort order to that view:
myView.ApplyDefaultSort = true;

This ensures that the Find method always has some criteria to sort by.


Let me know how it goes...
 
M

Mike Edenfield

Scave said:
Try something like this instead.
/**********/
TypedDataSet ds = _dataSet;
TypedDataSet.TableRow row = e.nodeData as TypedDataSet.TableRow;
CurrencyManager cm = BindingContext[ds, "Table"] as CurrencyManager;


DataView tableView = (DataView)cm.List;
int pos = tableView.Find(row.ID);

This works perfectly. The cm.List as a DataView was the part I was
missing. Thank you so much!

--Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top