Reading rows and columns from a DataGrid

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

Guest

I find it amazing that I am quickly able to find answers to obscure questions
but simple ones elude me.

I have a datagrid that I've bound, no problem at all. Now I want to -
programatically - loop through each row, extracting the data held in each
column.

I can't figure out how to do that. It has to be simple, can somebody please
help me?
 
Hi,

That;s not a very good idea to do, you see the datagrid is meant only to
make the data visible, not to retrieve it. for that use the binded source.

The reason is that the "data" itself may be transformed, maybe you have a
column that in the datasource was a double or a decimal and in the grid is
displayed as a currency formatted using the locate in place ( $XX,XXX.YY or
$XX.XXX,YY ) convert that back to the original value can be difficult

cheers,
 
I find it amazing that I am quickly able to find answers to obscure
questions
but simple ones elude me.

I have a datagrid that I've bound, no problem at all. Now I want to -
programatically - loop through each row, extracting the data held in each
column.

I can't figure out how to do that. It has to be simple, can somebody
please
help me?

I think you'd do it this way:

for (int rowIndex = 0; rowIndex < dataGrid.VisibleRowCount; rowIndex++)
for (int colIndex = 0; rowIndex < dataGrid.VisibleColCount; colIndex++)
{
object cellValue = dataGrid[rowIndex, colIndex];
... do something with cellValue here ...
}
 
I would agree with Igancio. It would be preferable to go through the actual
datasource as opposed to the grid. For one thing, performance-wise, it will
be much faster.

That said, I believe the indexer will return the underlying value and not
the transformed text, so that shouldn't be a problem.

Pete
 
Actually, I can think of several reasons you might want to: First of all, he
may be implementing code that works with a datagrid for use by other people.
He may not know what the data source is. A datagrid can be bound to any
object that IList or IListSource. If he doesn't know the nature of the data
source, then he would probably have to use the CurrencyManager to iterate
through the data. This would be unpleasant given the lack of documentation
of the CurrencyManager.

The easy solution would simply be to iterate through the grid cells and get
the data.

I'm not saying that's what he's doing, and iterating through the original
datasource may be the better solution for him. I'm simply saying, this is a
reason why that may not be preferable.

Pete
 
Pete,
How can he use the bindingmanager as he does not know the datasource, as
well how can he even get any data in a datagrid without a datasource?

I am really curious as you can show me how?

The documentation for the currencymanager is easy to find by the way and I
will not call this bad.

http://msdn.microsoft.com/library/d...stemwindowsformscurrencymanagerclasstopic.asp

Cor

Having implemented a hierarchical databound grid using the CurrencyManager,
I can promise you that the existing documentation was far from sufficient.
Were it not for tools like Reflector, it simply would have been impossible.

I'm sorry I wasn't more clear in my response. He may not know the specifics
of what the datasource is. That is to say, it could be a DataSet, a
DataTable, or any other IList or IListSource provider. Certainly he can get
the DataSource from the grid and he could then try to determine its type,
but from a generic point of view, he'd probably need to use the
CurrencyManager to then iterate through the data.

Now, one of the problems with doing this is that by iterating through the
CurrencyManager, he then going to implicitly force all bound controls to
iterate through the data as the Position changes. He could get around this
by creating a new BindingContext object and getting the CurrencyManager
from that, but the easiest thing would simply be to go through the grid.

As for the documentation issues, here's an example: The documentation says,
the CurrentChanged event "Occurs when the bound value changes." Well, that's
not very accurate at all. Changes how? If a value in a row in a bound
DataTable is changed? If the current row index (or CurrencyManager.Position)
changes?

The fact is, the CurrentChanged is sent for a variety of operations. If the
source implements IBindingList, then any ListChanged events will trigger a
CurrentChanged, regardless of whether the current item is the item affected
or not. Several other operations trigger a CurrentChanged whether or not the
record at the current CurrencyManager.Position is involved or not.

So the documentation for that one event is seriously misleading.

The MetaDataChanged event says that it "Occurs when the metadata of the List
has changed." Again, misleading in that it doesn't go on to say that this
only applies to objects that implement IBindingList. Any object implementing
IList but not IBindingList will not trigger a MetaDataChanged event if the
metadata of the list changes.

So yes, technically, it's documented, but the documentation is sorely
lacking in my opinion. I could go on and on all day about things about the
CurrencyManager that don't agree with the documentation. I'm intimately
familiar with both.

Pete
 
Hi,

No really, when each of the collection item is binded it's transformed
depending of the columns, for example, a bool column could be transformed in
a checkbox, the indexer ( at least in the case of the web grid ) is a
DataGridItem collection. It's difficult , if not impossible, to get from
the displayed grid back to the data itself.


cheers,
 
Hi,

First of all, this only apply to a win environment, the OP did not especify
if he is developing a win or web app ( nor he has posted back until now ).

If he is using a win app then you could keep a reference to the binded item
in that case, this could be done I think ,I do not have much experience
using the win datagrid but I'm pretty sure it can be done.

ITOH, you know for a fact that the datasource is iterable, so you could use
that fact along with reflection to try to access the original values.

cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
 
Hi,
First of all, this only apply to a win environment, the OP did not
especify if he is developing a win or web app ( nor he has posted back
until now ).

If he is using a win app then you could keep a reference to the binded
item in that case, this could be done I think ,I do not have much
experience using the win datagrid but I'm pretty sure it can be done.

ITOH, you know for a fact that the datasource is iterable, so you could
use that fact along with reflection to try to access the original values.

cheers,

Ignacio,

You're correct. You know that it implements IList or IListSource (I am
assuming the WinForm DataGrid, I don't do much web stuff. The web grid
obviously is completely different). But based on that, you could iterate
through the data and use reflection. Generally this will work. The problem
you can run into there is with reflection permissions. Generally not a
problem, but it can be in some cases.

That said, iterating over the indexer DOES work, regardless of the displayed
cell type. I just did a test with TextBox and CheckBox columns. My code was
slightly wrong. It should be (assuming that the add a new row is active):

for (int rowIndex = 0; rowIndex < dataGrid1.VisibleRowCount - 1; rowIndex++)
for (int colIndex = 0; colIndex < dataGrid1.VisibleColumnCount;
colIndex++)
{
object cellValue = dataGrid1[rowIndex, colIndex];
Debug.WriteLine(cellValue.ToString());
}



For example, in my grid, dataGrid1[0, 0] is a boolean column in the
datatable but a checkbox in the grid. dataGrid1[0, 0], returns a boxed
System.Boolean with the value of the cell.

Pete
 
Hi Pete,

I'm in the opposite side , I know a lot about the web grid and almost
nothing from the win version :)

cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation



Pete Davis said:
Hi,

First of all, this only apply to a win environment, the OP did not
especify if he is developing a win or web app ( nor he has posted back
until now ).

If he is using a win app then you could keep a reference to the binded
item in that case, this could be done I think ,I do not have much
experience using the win datagrid but I'm pretty sure it can be done.

ITOH, you know for a fact that the datasource is iterable, so you could
use that fact along with reflection to try to access the original values.

cheers,

Ignacio,

You're correct. You know that it implements IList or IListSource (I am
assuming the WinForm DataGrid, I don't do much web stuff. The web grid
obviously is completely different). But based on that, you could iterate
through the data and use reflection. Generally this will work. The problem
you can run into there is with reflection permissions. Generally not a
problem, but it can be in some cases.

That said, iterating over the indexer DOES work, regardless of the
displayed cell type. I just did a test with TextBox and CheckBox columns.
My code was slightly wrong. It should be (assuming that the add a new row
is active):

for (int rowIndex = 0; rowIndex < dataGrid1.VisibleRowCount - 1;
rowIndex++)
for (int colIndex = 0; colIndex < dataGrid1.VisibleColumnCount;
colIndex++)
{
object cellValue = dataGrid1[rowIndex, colIndex];
Debug.WriteLine(cellValue.ToString());
}



For example, in my grid, dataGrid1[0, 0] is a boolean column in the
datatable but a checkbox in the grid. dataGrid1[0, 0], returns a boxed
System.Boolean with the value of the cell.

Pete
 
Hi Pete,
I'm in the opposite side , I know a lot about the web grid and almost
nothing from the win version :)

cheers,

Ignacio,

Well, since the original poster didn't reply with which he's using, I figure
he has his answer whichever one it is :-)

Pete
 
Pete,

About what kind of DataGrid are you talking? When we are talking here about
a datagrid than it is a standard Microsoft WindowsForm datagrid or Webform
datagrid.

Both you can only populate using the datasource (or with winform its
databinding equivalent). For both you have to know what you are populating.
There is nothing to search. You know it.

Cor
 
Pete,
About what kind of DataGrid are you talking? When we are talking here
about a datagrid than it is a standard Microsoft WindowsForm datagrid or
Webform datagrid.

Both you can only populate using the datasource (or with winform its
databinding equivalent). For both you have to know what you are
populating. There is nothing to search. You know it.

Cor


I'm thinking in terms of the WinForm datagrid. I don't know much about
WebForms datagrid.

Okay, let's say, for example, I write an library that adds functionality to
the datagrid. Then other people use this library. My library needs to access
data in the grid as part of its function. I do not, beforehand, know the
exact nature of the data being bound to the grid. All I know is that it must
implement either IList or IListSource. Beyond that, I know nothing else
about the data beforehand.

My point being, if I need find out the contents of the data as part of my
library, the easiest way is going to be directly through the grid indexer.
It's not necessarily the best way, but it's certainly the easiest way.


Pete
 
Pete,
Okay, let's say, for example, I write an library that adds functionality
to the datagrid.

Than it is not a standard windowsform datagrid. In addition from a bad
design if you can not use the datasource of that.

Cor
 
Back
Top