DataGrid and DataView question

G

Guest

I inherited some code that binds a dataset/datatable to a datagrid. When the
user highlights some rows the code loops thru a DataView of the grid to act
on those rows. This works fine, unless you first click a column to sort by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in at
least the intention here?
 
D

Darren Shaffer

Tim,

There is no bug, you just need to understand the DataRowView and
CurrencyManager
behavior. Rather than write an essay here, instead I'll just give you the
code to make
sure your selection is correct after sorting. This code is for a DataGrid
that contains
a list of car dealerships.

private void dgDealership_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( dgDealership.VisibleRowCount == 0 )
return;

SortDataGrid(sender, e);

dgDealership.Select(dgDealership.CurrentRowIndex);
CurrencyManager cm =
(CurrencyManager)BindingContext[dgDealership.DataSource];

DataRowView drv = (DataRowView)cm.Current;

lblDealerName.Text = drv.Row[0].ToString();
lblDealerAddress.Text = drv.Row[1].ToString();

_dealerSelected = drv.Row[5].ToString();

}

public static void SortDataGrid(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hitTest;
DataTable dataTable;
DataView dataView;
string columnName;
DataGrid dataGrid;

if (e.Button == MouseButtons.Left)
{
dataGrid = (DataGrid)sender;
hitTest = dataGrid.HitTest(e.X, e.Y);
if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
{
dataTable = (DataTable)dataGrid.DataSource;
dataView = dataTable.DefaultView;

if(dataGrid.TableStyles.Count != 0)
columnName =
dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName;
else
columnName = dataTable.Columns[hitTest.Column].ColumnName;

if (dataView.Sort == columnName)
dataView.Sort = columnName + " DESC";
else
dataView.Sort = columnName;
}
}
}

--
Darren Shaffer
..NET Compact Framework MVP
Principal Architect
Connected Innovation
www.connectedinnovation.com



Tim Johnson said:
I inherited some code that binds a dataset/datatable to a datagrid. When
the
user highlights some rows the code loops thru a DataView of the grid to
act
on those rows. This works fine, unless you first click a column to sort
by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but
I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in
at
least the intention here?
 
G

Guest

Thanks, I see what you're doing. I'd say it is a bug in the code I inherited
though since the person didn't manage the sorting himself! I'll adjust the
code as you indicated and all the objects will sort together.

Darren Shaffer said:
Tim,

There is no bug, you just need to understand the DataRowView and
CurrencyManager
behavior. Rather than write an essay here, instead I'll just give you the
code to make
sure your selection is correct after sorting. This code is for a DataGrid
that contains
a list of car dealerships.

private void dgDealership_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( dgDealership.VisibleRowCount == 0 )
return;

SortDataGrid(sender, e);

dgDealership.Select(dgDealership.CurrentRowIndex);
CurrencyManager cm =
(CurrencyManager)BindingContext[dgDealership.DataSource];

DataRowView drv = (DataRowView)cm.Current;

lblDealerName.Text = drv.Row[0].ToString();
lblDealerAddress.Text = drv.Row[1].ToString();

_dealerSelected = drv.Row[5].ToString();

}

public static void SortDataGrid(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hitTest;
DataTable dataTable;
DataView dataView;
string columnName;
DataGrid dataGrid;

if (e.Button == MouseButtons.Left)
{
dataGrid = (DataGrid)sender;
hitTest = dataGrid.HitTest(e.X, e.Y);
if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
{
dataTable = (DataTable)dataGrid.DataSource;
dataView = dataTable.DefaultView;

if(dataGrid.TableStyles.Count != 0)
columnName =
dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName;
else
columnName = dataTable.Columns[hitTest.Column].ColumnName;

if (dataView.Sort == columnName)
dataView.Sort = columnName + " DESC";
else
dataView.Sort = columnName;
}
}
}

--
Darren Shaffer
..NET Compact Framework MVP
Principal Architect
Connected Innovation
www.connectedinnovation.com



Tim Johnson said:
I inherited some code that binds a dataset/datatable to a datagrid. When
the
user highlights some rows the code loops thru a DataView of the grid to
act
on those rows. This works fine, unless you first click a column to sort
by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but
I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in
at
least the intention here?

 
G

Guest

Two followup questions. Here's the first:

I can see the underlying dataview being sorted when I use your code, so when
I click on column "XYZ" I see it sorted ascending when I stop in the
debugger. When I let it go however it ends up sorted DEscending. It's as
though I've sorted the underlying source, which the grid sticks with, then
afterwards the grid control does its own sort. And since by the time he sees
it he thinks the click on column XYZ is a 2nd sort. How can I override the
datagrid's "extra" sort, if in fact that's what's happeing?

Tim

Darren Shaffer said:
Tim,

There is no bug, you just need to understand the DataRowView and
CurrencyManager
behavior. Rather than write an essay here, instead I'll just give you the
code to make
sure your selection is correct after sorting. This code is for a DataGrid
that contains
a list of car dealerships.

private void dgDealership_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( dgDealership.VisibleRowCount == 0 )
return;

SortDataGrid(sender, e);

dgDealership.Select(dgDealership.CurrentRowIndex);
CurrencyManager cm =
(CurrencyManager)BindingContext[dgDealership.DataSource];

DataRowView drv = (DataRowView)cm.Current;

lblDealerName.Text = drv.Row[0].ToString();
lblDealerAddress.Text = drv.Row[1].ToString();

_dealerSelected = drv.Row[5].ToString();

}

public static void SortDataGrid(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hitTest;
DataTable dataTable;
DataView dataView;
string columnName;
DataGrid dataGrid;

if (e.Button == MouseButtons.Left)
{
dataGrid = (DataGrid)sender;
hitTest = dataGrid.HitTest(e.X, e.Y);
if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
{
dataTable = (DataTable)dataGrid.DataSource;
dataView = dataTable.DefaultView;

if(dataGrid.TableStyles.Count != 0)
columnName =
dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName;
else
columnName = dataTable.Columns[hitTest.Column].ColumnName;

if (dataView.Sort == columnName)
dataView.Sort = columnName + " DESC";
else
dataView.Sort = columnName;
}
}
}

--
Darren Shaffer
..NET Compact Framework MVP
Principal Architect
Connected Innovation
www.connectedinnovation.com



Tim Johnson said:
I inherited some code that binds a dataset/datatable to a datagrid. When
the
user highlights some rows the code loops thru a DataView of the grid to
act
on those rows. This works fine, unless you first click a column to sort
by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but
I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in
at
least the intention here?

 
G

Guest

Here's the second one:

I implemented the Sort logic so that when you click a column header to sort,
the grid and the dataset stay in sync. But when I attempt to pick off a
column value of a selected row I get two different results depending on which
statement I use (the "bad" one was in some legacy code; the "good" one is
based on your email).

First I get the DataView and selected row index:

CurrencyManager cm = (CurrencyManager) dg.BindingContext[dg.DataSource,
dg.DataMember];
DataView dv = (DataView)cm.List;
int index = dg.CurrentRowIndex;

Then this gets me the "right" value from the newly sorted list:
DataRowView drv = dv[index];
string s = drv["myfield"].ToString();

This gets me the "old" value from the original unsorted list:
DataRowdr = dv.Table.Rows[index];
string s = dr["myfield"].ToString();

Basically, how does dv relate to dv.Table.Rows when there's a Sort
property set? Are there two dataviews at work here somehow?


Darren Shaffer said:
Tim,

There is no bug, you just need to understand the DataRowView and
CurrencyManager
behavior. Rather than write an essay here, instead I'll just give you the
code to make
sure your selection is correct after sorting. This code is for a DataGrid
that contains
a list of car dealerships.

private void dgDealership_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( dgDealership.VisibleRowCount == 0 )
return;

SortDataGrid(sender, e);

dgDealership.Select(dgDealership.CurrentRowIndex);
CurrencyManager cm =
(CurrencyManager)BindingContext[dgDealership.DataSource];

DataRowView drv = (DataRowView)cm.Current;

lblDealerName.Text = drv.Row[0].ToString();
lblDealerAddress.Text = drv.Row[1].ToString();

_dealerSelected = drv.Row[5].ToString();

}

public static void SortDataGrid(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hitTest;
DataTable dataTable;
DataView dataView;
string columnName;
DataGrid dataGrid;

if (e.Button == MouseButtons.Left)
{
dataGrid = (DataGrid)sender;
hitTest = dataGrid.HitTest(e.X, e.Y);
if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
{
dataTable = (DataTable)dataGrid.DataSource;
dataView = dataTable.DefaultView;

if(dataGrid.TableStyles.Count != 0)
columnName =
dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName;
else
columnName = dataTable.Columns[hitTest.Column].ColumnName;

if (dataView.Sort == columnName)
dataView.Sort = columnName + " DESC";
else
dataView.Sort = columnName;
}
}
}

--
Darren Shaffer
..NET Compact Framework MVP
Principal Architect
Connected Innovation
www.connectedinnovation.com



Tim Johnson said:
I inherited some code that binds a dataset/datatable to a datagrid. When
the
user highlights some rows the code loops thru a DataView of the grid to
act
on those rows. This works fine, unless you first click a column to sort
by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but
I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in
at
least the intention here?

 
G

Guest

Doh! My mistake on the 2nd question - obviously the dv.Table reference puts
you back in the original (unsorted) DataTable so the Sort property doesn't
apply. Never mind!

Tim Johnson said:
Here's the second one:

I implemented the Sort logic so that when you click a column header to sort,
the grid and the dataset stay in sync. But when I attempt to pick off a
column value of a selected row I get two different results depending on which
statement I use (the "bad" one was in some legacy code; the "good" one is
based on your email).

First I get the DataView and selected row index:

CurrencyManager cm = (CurrencyManager) dg.BindingContext[dg.DataSource,
dg.DataMember];
DataView dv = (DataView)cm.List;
int index = dg.CurrentRowIndex;

Then this gets me the "right" value from the newly sorted list:
DataRowView drv = dv[index];
string s = drv["myfield"].ToString();

This gets me the "old" value from the original unsorted list:
DataRowdr = dv.Table.Rows[index];
string s = dr["myfield"].ToString();

Basically, how does dv relate to dv.Table.Rows when there's a Sort
property set? Are there two dataviews at work here somehow?


Darren Shaffer said:
Tim,

There is no bug, you just need to understand the DataRowView and
CurrencyManager
behavior. Rather than write an essay here, instead I'll just give you the
code to make
sure your selection is correct after sorting. This code is for a DataGrid
that contains
a list of car dealerships.

private void dgDealership_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( dgDealership.VisibleRowCount == 0 )
return;

SortDataGrid(sender, e);

dgDealership.Select(dgDealership.CurrentRowIndex);
CurrencyManager cm =
(CurrencyManager)BindingContext[dgDealership.DataSource];

DataRowView drv = (DataRowView)cm.Current;

lblDealerName.Text = drv.Row[0].ToString();
lblDealerAddress.Text = drv.Row[1].ToString();

_dealerSelected = drv.Row[5].ToString();

}

public static void SortDataGrid(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hitTest;
DataTable dataTable;
DataView dataView;
string columnName;
DataGrid dataGrid;

if (e.Button == MouseButtons.Left)
{
dataGrid = (DataGrid)sender;
hitTest = dataGrid.HitTest(e.X, e.Y);
if (hitTest.Type == DataGrid.HitTestType.ColumnHeader)
{
dataTable = (DataTable)dataGrid.DataSource;
dataView = dataTable.DefaultView;

if(dataGrid.TableStyles.Count != 0)
columnName =
dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName;
else
columnName = dataTable.Columns[hitTest.Column].ColumnName;

if (dataView.Sort == columnName)
dataView.Sort = columnName + " DESC";
else
dataView.Sort = columnName;
}
}
}

--
Darren Shaffer
..NET Compact Framework MVP
Principal Architect
Connected Innovation
www.connectedinnovation.com



Tim Johnson said:
I inherited some code that binds a dataset/datatable to a datagrid. When
the
user highlights some rows the code loops thru a DataView of the grid to
act
on those rows. This works fine, unless you first click a column to sort
by
that column. Then the datagrid rows are not in the same sequence as the
datasource table. I'm thinking this is a definite bug in this code, but
I'm
wondering what the point of doing things this way might have been. I mean
why bother with CurrencyManager and DataView if you can just access the
elements via datagrid1[row, col]?

Here's an example of the loop which seems overkill to me (besides not
working if you sort first!):

CurrencyManager mgr = (CurrencyManager)
dataGrid1.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

DataView dv = (DataView)mgr.List;

for (int i = 0; i < dv.Count; ++i)
{
if (dataGrid1.IsSelected(i))
{
DataRow row = dv.Table.Rows;

<get a field from row here...>
}
}

I mean, if the datagrid got sorted, the underlying datatable or dataview
isn't also sorted is it? So highlighted row 1 in a sorted datagrid is NOT
row 1 in the presorted datatable or dataview. Am I missing something in
at
least the intention here?

 

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