How to copy a row in a Dataview based on user selection?

  • Thread starter Thread starter Michael Kellogg
  • Start date Start date
M

Michael Kellogg

I have a datatable that I'm displaying in a Winform Datagrid via a
DataView, and I want the user to be able to right-click on any of the rows
and select a "copy row" command from a context menu. Then I need to make
the copy happen.

I've got the context menu up and responding appropriately, but I'm having
difficulty dealing with the copying:

Firstly, how do I identify what row the user wants to copy?

Second, how do I make a copy of the row? There is no "Clone" method for
a row. Do I need to do an element-by-element copy of the row? And if so,
can I do this with an enumerator or must I use column names?


I've been struggling with this for a half a day; I'd sure appreciate any
help.
 
Michael,
To find the current dataRow try

DataView dataView = (DataView)((CurrencyManager)
dataGrid1.BindingContext[ dataGrid1.DataSource, dataGrid1.DataMember
]).List;
DataRow dataRow = dataView[ dataGrid1.CurrentRowIndex ].Row;

To copy the row into another dataTable (with the same structure) try

destinationTable.Rows.Add(dataRow.ItemArray);

All the Best,
Phil.
 
Michael,
To find the current dataRow try

DataView dataView = (DataView)((CurrencyManager)
dataGrid1.BindingContext [dataGrid1.DataSource,
dataGrid1.DataMember]).List;
DataRow dataRow = dataView[ dataGrid1.CurrentRowIndex ].Row;

To copy the row into another dataTable (with the same structure) try
destinationTable.Rows.Add(dataRow.ItemArray);

All the Best,
Phil.


Thanks for the help, Phil. I'm still trying to understand exactly what
you're doing, here. I've never really understood BindingManagerBase
objects and their function. I like the way you added a copy of a row
without really cloning it; I would not have thought of that.

One issue I'm having is that, when capturing the right-click that brings
up the context menu, if you click on the row itself (the technical term
escapes me; the little box on the left side of a row), the
CurrentRowIndex property does NOT seem to update with that row. You have
to actually click on a cell inside the row. Consequently, the row
returned is wrong. I tried doing a SELECT on the row identified in the
MouseDown event handler (where the use of HitTest will give me the
correct row index), but this doesn't seem to work, either. Is there a
way to "activate" a row so the CurrentRowIndex property is guaranteed to
be right?

Thanks again for the help.
MK
 
Michael,
In contextMenu_Popup, try

DataGrid.HitTestInfo hti = dataGrid1.HitTest(
dataGrid1.PointToClient(Control.MousePosition));

if (hti.Row != -1)
{
DataView dataView = (DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
DataRow dataRow = dataView[ hti.Row ].Row;
}

Cheers,
Phil.

Michael Kellogg said:
Michael,
To find the current dataRow try

DataView dataView = (DataView)((CurrencyManager)
dataGrid1.BindingContext [dataGrid1.DataSource,
dataGrid1.DataMember]).List;
DataRow dataRow = dataView[ dataGrid1.CurrentRowIndex ].Row;

To copy the row into another dataTable (with the same structure) try
destinationTable.Rows.Add(dataRow.ItemArray);

All the Best,
Phil.


Thanks for the help, Phil. I'm still trying to understand exactly what
you're doing, here. I've never really understood BindingManagerBase
objects and their function. I like the way you added a copy of a row
without really cloning it; I would not have thought of that.

One issue I'm having is that, when capturing the right-click that brings
up the context menu, if you click on the row itself (the technical term
escapes me; the little box on the left side of a row), the
CurrentRowIndex property does NOT seem to update with that row. You have
to actually click on a cell inside the row. Consequently, the row
returned is wrong. I tried doing a SELECT on the row identified in the
MouseDown event handler (where the use of HitTest will give me the
correct row index), but this doesn't seem to work, either. Is there a
way to "activate" a row so the CurrentRowIndex property is guaranteed to
be right?

Thanks again for the help.
MK
 
"=?Utf-8?B?UGhpbCBXaWxsaWFtcw==?="
Michael,
In contextMenu_Popup, try

DataGrid.HitTestInfo hti = dataGrid1.HitTest(
dataGrid1.PointToClient(Control.MousePosition));

if (hti.Row != -1)
{
DataView dataView =
(DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
DataRow dataRow = dataView[ hti.Row ].Row;
}

That is very clever; I like it. Any chance I can do something like this
in the MenuItem CLICK handler instead (obviously the mouse will have
moved by the time I select a context menu item)? I can get the row using
your method either in the POPUP, as you suggest, or in the datagrid CLICK
handler, as well. Then my thought was to stash the row number in a
member variable and use it in the MenuItem CLICK handler. However, this
didn't seem so elegant to me and I thought it'd be nice to actually
determine the row inside the handler. Am I obsessing?
 
Michael,
Add the following lines

private int clickedRow = -1;
..
..
..
private void contextMenu_Popup(object sender, System.EventArgs e)
{
DataGrid.HitTestInfo hti = dataGrid1.HitTest(
dataGrid1.PointToClient(Control.MousePosition));
clickedRow = hti.Row;
menuItemCopyRow.Enabled = clickedRow != -1;
}

private void menuItemCopyRow_Click(object sender, System.EventArgs e)
{
if (clickedRow == -1) return;
DataView dataView =
(DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
DataRow dataRow = dataView[ clickedRow ].Row;
}

All the best,
Phil.





Michael Kellogg said:
"=?Utf-8?B?UGhpbCBXaWxsaWFtcw==?="
Michael,
In contextMenu_Popup, try

DataGrid.HitTestInfo hti = dataGrid1.HitTest(
dataGrid1.PointToClient(Control.MousePosition));

if (hti.Row != -1)
{
DataView dataView =
(DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
DataRow dataRow = dataView[ hti.Row ].Row;
}

That is very clever; I like it. Any chance I can do something like this
in the MenuItem CLICK handler instead (obviously the mouse will have
moved by the time I select a context menu item)? I can get the row using
your method either in the POPUP, as you suggest, or in the datagrid CLICK
handler, as well. Then my thought was to stash the row number in a
member variable and use it in the MenuItem CLICK handler. However, this
didn't seem so elegant to me and I thought it'd be nice to actually
determine the row inside the handler. Am I obsessing?
 
Michael,
Add the following lines

private int clickedRow = -1;
.
.
.
private void contextMenu_Popup(object sender, System.EventArgs e)
{
DataGrid.HitTestInfo hti = dataGrid1.HitTest(
dataGrid1.PointToClient(Control.MousePosition));
clickedRow = hti.Row;
menuItemCopyRow.Enabled = clickedRow != -1;
}

private void menuItemCopyRow_Click(object sender, System.EventArgs e)
{
if (clickedRow == -1) return;
DataView dataView =
(DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
DataRow dataRow = dataView[ clickedRow ].Row;
}

All the best,
Phil.


Thanks, Phil!
-mk
 
Back
Top