How to get Columns in DataGridViewRowSelectedRowCollection - c#

Ok guys, I thought this would be easier than it is.
public static DataRowCollection ToRows(this DataGridViewSelectedRowCollection Rows)
{
DataTable table = new DataTable();
foreach (DataColumn column in Rows[0].DataGridView.Columns)
{
table.Columns.Add(column);
}
foreach (DataGridViewRow row in Rows)
{
DataRow newRow = ((DataRowView)row.DataBoundItem).Row;
table.ImportRow(newRow);
}
return table.Rows;
}
I'm trying to get the columns of a row in a DataGridViewSelectedRowCollection. The code above throws an InvalidCast error on the table.Columns.Add(column) because it is trying to cast DataGridViewColumns to DataTable columns. I dont have access to the DataGridView because I am in a static method that Extends the DataGridViewSelectedRowCollection and do not have access to the DataGridView.
How can I cast the columns collection to a DataColumns object?

You can create an extension method to return the data rows behind selected rows of grid this way:
public static class DataGridViewExtensions
{
public static List<DataRow> ToDataRows(this DataGridViewSelectedRowCollection Rows)
{
if (Rows == null || Rows.Count == 0)
return null;
return Rows.Cast<DataGridViewRow>()
.Where(x => x.DataBoundItem is DataRowView)
.Select(x => ((DataRowView)(x.DataBoundItem)).Row).ToList();
}
}
Then to get values from a row variable of type DataRow, consider using these options:
row.ItemArray contains all column values
row[index] gets the value of a column by index
row["column name"] gets the value of column by column name
row.Table.Columns contains a list of columns of DataTable

Related

How to copy values from a datatable column into a datagridview column in windows forms in c# without iterating every single row?

I have more than 9000 rows and 18 columns in my datagridview. I have to read the columns from an external datatable. If I find a match between column names, I have to copy all values from the datatable column into the datagridview column. My problem is, I cannot iterate over these rows for 18 times for more than 9000 rows and write for every iteration the value in the datagridview cell because it is too slow. Is there any valid alternative?
I add some code below so that you can understand better my question. Here I'm iterating the columns first, then the rows. Sorry for the indentation but I'm having problems in copy paste code on StackOverflow.
dgvMappatura is my dataGridView, dtExcel is my DataTable
foreach (DataColumn col in dtExcel.Columns)
{
if (col.ColumnName.Equals(nome_colonna_origine))
{
foreach (DataRow drExcel in dtExcel.Rows)
{
// some code to add values to datagridview from the datatable column
}
}
}
See if following is faster :
DataTable dt = new DataTable();
foreach (DataRow row in dt.AsEnumerable())
{
var matches = row.ItemArray.Select((x, i) => new { name = x.ToString(), index = i }).GroupBy(x => x.name).Where(x => x.Count() > 1).ToArray();
}

Get specific column from DataRow without iteration through every column

Im new to DataSets and I am trying to get a specific column from a DataSet. I wrote this code
using (var dataset = new U2ZFDataSetTableAdapters.stationenTableAdapter())
{
var ds = new U2ZFDataSet();
dataset.Fill(ds.stationen);
var rows = ds.stationen.Select("pdvorhanden = 1");
foreach (DataRow row in rows)
{
foreach (DataColumn column in ds.stationen.Columns)
{
if(column.ColumnName == "Bezeichnung")
listOfStations.Add(row[column].ToString());
}
}
}
The code feels slow to me. Isnt there a better way to do this? How can I get a specific Colum from DataRow without iterating through every column of the row?
Access to the column via column name.
foreach (DataRow row in rows)
{
listOfStations.Add(row["Bezeichnung"].ToString());
}
https://msdn.microsoft.com/en-us/library/146h6tk5(v=vs.110).aspx

Looping though columns to store in session

So I have a DataTable which uses a "SELECT * FROM People WHERE ID = ?" you can understand that this will only retrieve one row as the ID is unique
I have casted it to a list:
List<DataTable> userInfo = (List<DataTable>)HttpContext.Current.Session["userDT"];
Now I am trying to do a foreach loop that would loop through each row and store the column into a session, this is what I have so far:
However I get an error:
Cannot convert type 'System.Data.DataTable' to 'System.Data.DataRow'
Does anyone know what I am doing wrong?
userInfo is a list of tables. You have to iterate through it, and for each table you can access that table's rows:
foreach (DataTable dt in userInfo)
{
foreach (DataColumn column in dt.Columns)
{
// if you want column names here is how you would get them
string columnName = column.ColumnName;
foreach (DataRow row in dt.Rows)
{
// if you want the values in the cells, here's where you get them
object value = row[column];
}
}
}

Adding DataColumn to DataTable

I want to move the data from a dataColumn to a specific column in my dataTable. I am not sure how to specify what column within my Datatable I want to add the datacolumn.
foreach (DataColumn col in dt.Columns)
{
dt1.Columns.Add(col);
}
I receive an exception Column 'X' already belongs to another DataTable.
You need to copy the properties like ColumnName and create new DataColumns:
foreach (DataColumn col in dt.Columns)
{
dt1.Columns.Add(col.ColumnName, col.DataType);
}
There's a reason for the ArgumentException when you add a DataColumn which already belongs to another DataTable. It would be very dangerous to allow that since a DataTable holds a reference to their columns and every column holds a reference to it's DataTable. If you would add a column to another table your code would blow sooner or later.
If you also want to copy the DataRows into the new table:
foreach (DataRow row in t1.Rows)
{
var r = t2.Rows.Add();
foreach (DataColumn col in t2.Columns)
{
r[col.ColumnName] = row[col.ColumnName];
}
}
You cannot add a DataColumn from another table, because it already has an association with it's original table and a DataColumn is passed by reference to the Add method because it's an Object. You'll have to copy it. Here's one way you can do that:
public static class DataColumnExtensions
{
public static DataColumn CopyTo(this DataColumn column, DataTable table)
{
DataColumn newColumn = new DataColumn(column.ColumnName, column.DataType, column.Expression, column.ColumnMapping);
newColumn.AllowDBNull = column.AllowDBNull;
newColumn.AutoIncrement = column.AutoIncrement;
newColumn.AutoIncrementSeed = column.AutoIncrementSeed;
newColumn.AutoIncrementStep = column.AutoIncrementStep;
newColumn.Caption = column.Caption;
newColumn.DateTimeMode = column.DateTimeMode;
newColumn.DefaultValue = column.DefaultValue;
newColumn.MaxLength = column.MaxLength;
newColumn.ReadOnly = column.ReadOnly;
newColumn.Unique = column.Unique;
table.Columns.Add(newColumn);
return newColumn;
}
public static DataColumn CopyColumnTo(this DataTable sourceTable, string columnName, DataTable destinationTable)
{
if (sourceTable.Columns.Contains(columnName))
{
return sourceTable.Columns[columnName].CopyTo(destinationTable);
}
else
{
throw new ArgumentException("The specified column does not exist", "columnName");
}
}
}
public class MyClass
{
public static void Main()
{
DataTable tableA = new DataTable("TableA");
tableA.Columns.Add("Column1", typeof(int));
tableA.Columns.Add("Column2", typeof(string));
DataTable tableB = new DataTable("TableB");
foreach (DataColumn column in tableA.Columns)
{
column.CopyTo(tableB);
}
}
}
Note that there is also an extension method that can be used to Copy individual columns by name, i.e. tableA.CopyColumnTo("Column1", tableB);.
Then you can copy the data like this if the new table is an exact copy of the original:
foreach (DataRow row in tableA.Rows)
{
tableB.Rows.Add(row.ItemArray);
}
Or in a way similar to the second piece of code in Tim Schmelter's answer if it is not an exact copy. I would, however, recommend some error checking if you aren't copying all the columns into the new table:
foreach (DataRow souceRow in sourceTable.Rows)
{
DataRow destinationRow = destinationTable.Rows.Add();
foreach (DataColumn destinationColumn in destinationTable.Columns)
{
string columnName = destinationColumn.ColumnName;
if (sourceTable.Columns.Contains(columnName))
{
destinationRow[columnName] = sourceRow[columnName];
}
}
}
this is a normal behavior, if you're adding the same column to more than one DataTable ArgumentException will be thrown.
see documentation here:
http://msdn.microsoft.com/en-us/library/55b10992.aspx
you can create a new column same as the one you already added to the original table and add it to the new table.
Table data is organized by row, then by column. You can't (that I know of) add a column of data in one shot. You will need to add the column definition to the second table and add the data to it separately.
Since your original code looped through all columns, you may be better off copying the original datatable using DataTable.Copy() and deleting what you don't want.

Changing IEnumerable<object> into DataRow[]

I need to get a value of a column of a table, which is at the same row of a specified row. I use the IEnumerable to find it. But the result cannot be transferred into 'foreach', l wish to change it into DataRow[], can any1 help me with this? here's my code:
//I wish to change it into DataRow[] findPccID
IEnumerable<object> findPccID = DataSet1.Tables["Pcc"].Select("ID=" + ID).Select(a => a["PccID"]);
foreach (DataRow row in findPccID) // 'InvalidCastException was unhandled' occurs here
{
//codes
}
You are selecting a column. It should be.
//I wish to change it into DataRow[] findPccID
DataRow[] findPccID = DataSet1.Tables["Pcc"].Select("ID=" + ID);
foreach (DataRow row in findPccID)
{
//You can select the PccId here
}

Categories