I have a datatable with 17 columns and a bunch of data.
I wnat a datatable with only 6 of the columns and the data for those 6 columns.
So I need a subset of the original datatable.
How do I loop through the original datatable with 17 columns and end up with a datatable with only the 6 columns I want with the corresponding data for those 6 columns?
Private Function createSmallCopyofExistingTable(ByVal SourceTable As DataTable) As DataTable
Dim newTable As DataTable = New DataTable()
'Copy Only 6 columns from the datatable
Dim ColumnsToExport() As String = {"ID", "FirstName", "LastName", "DateOfBirth", "City", "State"}
newTable = SourceTable.DefaultView.ToTable("tempTableName", False, ColumnsToExport)
Return newTable
End Function
Without knowing more about how generic this needs to be its really just...
foreach (DataRow dr in dt.Rows)
{
newDt.Rows.Add(dr["col1"],dr["col5"],etc);
}
what about data types, and columns? are these same? if yes, you can create
object[] row = new object[]{// Fill your rows manually};
before filling it create
DataTable dt = new DataTable();
dt.Columns.Add("Title",typeof(string etc..));.....
and finally
dt.Rows.Add(row);
Personally, I would avoid creating another instance of a DataTable.
It depends on your situation, of course, but if this is purely for usability and not for security (i.e. you're not trying to remove columns with sensitive data before transmitting it somewhere), then I would create a wrapper object that encapsulates the columns that you want to expose.
The benefit of using a wrapper is in case you are doing any updates, then you can update the source table directly rather than the copy. Whether this really matters, of course, depends on your situation.
A simple example with limited functionality:
public class MyFormOrPage
{
void UsageExample()
{
DataTable allDataTable = new DataTable();
// populate the data table with whatever logic ...
// wrap the data table to expose only the Name, Address, and PhoneNumber columns
var limitedDataTable = new DataTableWrapper(allDataTable, "Name", "Address", "PhoneNumber");
// iterate over the rows
foreach (var limitedDataRow in limitedDataTable)
{
// iterate over the columns
for (int i = 0; i < limitedDataTable.ColumnCount; i++)
{
object value = limitedDataRow[i];
// do something with the value ...
}
}
// bind the wrapper to a control
MyGridControl.DataSource = limitedDataTable;
}
}
public class DataTableWrapper : IEnumerable<DataRowWrapper>
{
private DataTable _Table;
private string[] _ColumnNames;
public DataTableWrapper(DataTable table, params string[] columnNames)
{
this._Table = table;
this._ColumnNames = columnNames;
}
public int ColumnCount
{
get { return this._ColumnNames.Length; }
}
public IEnumerator<DataRowWrapper> GetEnumerator()
{
foreach (DataRow row in this._Table.Rows)
{
yield return new DataRowWrapper(row, this._ColumnNames);
}
}
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
// if you _really_ want to make a copy of the DataTable, you can use this method
public DataTable CopyToDataTable()
{
DataTable copyTable = new DataTable();
for (int index = 0; index < this._ColumnNames.Length; index++)
{
DataColumn column = this._Table.Columns[index];
copyTable.Columns.Add(column);
}
foreach (DataRow row in this._Table.Rows)
{
DataRow copyRow = copyTable.NewRow();
for (int index = 0; index < this._ColumnNames.Length; index++)
{
copyRow[index] = row[this._ColumnNames[index]];
}
copyTable.Rows.Add(copyRow);
}
return copyTable;
}
}
// let's make this a struct, since potentially very many of these will be instantiated
public struct DataRowWrapper
{
private DataRow _Row;
private string[] _ColumnNames;
public DataRowWrapper(DataRow row, params string[] columnNames)
{
this._Row = row;
this._ColumnNames = columnNames;
}
// use this to retrieve column values from a row
public object this[int index]
{
get { return this._Row[this._ColumnNames[index]]; }
set { this._Row[this._ColumnNames[index]] = value; }
}
// just in case this is still needed...
public object this[string columnName]
{
get { return this._Row[columnName]; }
set { this._Row[columnName] = value; }
}
}
Related
I created a class that's responsible to evaluate an expression values for the row when I need it but the problem that when my methods works very slow in big datatables.
public static class RowExpressionEvaluator
{
public static object EvaluateValue(DataRow row, string expression, Type outputType)
{
if (row == null) throw new ArgumentNullException(nameof(row));
return EvaluateValue(row.Table, row, expression, outputType);
}
private static object EvaluateValue(DataTable table, DataRow row, string expression, Type outputType)
{
if (table == null) throw new ArgumentNullException(nameof(table));
if (row == null) throw new ArgumentNullException(nameof(row));
if (string.IsNullOrEmpty(expression)) throw new ArgumentException("Expression cannot be null or empty.", nameof(expression));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException(#"The rowState is detached.");
object result = null;
using (var tempColumn = new DataColumn("Exp", outputType))
{
table.Columns.Add(tempColumn);
tempColumn.Expression = expression;
if (!row[tempColumn.ColumnName].IsDbNull())
result = row[tempColumn.ColumnName];
table.Columns.Remove(tempColumn);
}
return result;
}
}
This code works fine but its slow when the datatable contains big data
I tried to improve this code so when I have many expressions to evaluate
then when I finish I dispose it it works better but still needs to improve because I think when I add the column with an expression the datatable evaluate it for all the rows but I need to evaluate the value only for the passed row.
like this one :
public sealed class BetterRowExpressionEvaluator :IDisposable
{
private readonly DataRow _row;
private readonly DataColumn _expressionColumn;
public BetterRowExpressionEvaluator(DataRow row)
{
_row = row ?? throw new ArgumentNullException(nameof(row));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException(#"The rowState is detached.");
_expressionColumn = new DataColumn("Expression",typeof(object));
DataTable table = _row.Table;
table.Columns.Add(_expressionColumn);
}
public object Evaluate(string expression)
{
if (string.IsNullOrEmpty(expression)) throw new ArgumentException("Value cannot be null or empty.", nameof(expression));
_expressionColumn.Expression = expression;
return !_row[_expressionColumn.ColumnName].IsDbNull() ? _row[_expressionColumn.ColumnName] : null;
}
public void Dispose()
{
if (_expressionColumn == null) return;
DataTable table = _row.Table;
table.Columns.Remove(_expressionColumn);
_expressionColumn?.Dispose();
}
}
I did something like this to clone the row and it's parent and child relations so when I evaluate the expressions it comes faster and this is what I did :
private DataSet CloneTableWithRelations(DataRow row)
{
var dataset = new DataSet("EvaluationDataSet") {Locale = CultureInfo.InvariantCulture};
dataset.Tables.Add(row.Table.Clone());
dataset.Tables[row.Table.TableName].ImportRow(row);
foreach (DataRelation parentRelation in row.Table.ParentRelations)
{
string relationName = parentRelation.RelationName;
DataTable parentTable = parentRelation.ParentTable;
// clone the parent table
dataset.Tables.Add(parentTable.Clone());
// copy the parent rows related only to the passed row
DataRow parentRow= row.GetParentRow(relationName);
dataset.Tables[parentTable.TableName].ImportRow(parentRow);
DataColumn parentColumn=parentRelation.ParentColumns[0];
DataColumn childColumn=parentRelation.ChildColumns[0];
dataset.Relations.Add(relationName, parentColumn, childColumn,false);
}
foreach (DataRelation dataRelation in row.Table.ChildRelations)
{
DataTable childTable = dataRelation.ChildTable;
// clone the parent table
dataset.Tables.Add(childTable.Clone());
// copy the parent rows related only to the passed row
foreach (DataRow childRow in row.GetChildRows(dataRelation.RelationName))
{
dataset.Tables[childTable.TableName].ImportRow(childRow);
}
DataColumn parentColumn=dataRelation.ParentColumns[0];
DataColumn childColumn=dataRelation.ChildColumns[0];
dataset.Relations.Add(dataRelation.RelationName, parentColumn, childColumn,false);
}
return dataset;
}
is there a better way to do it and more reliable way ?
Finally It works much better
when I clone the row and its parent and child data
using this class I've created
public class RowCloneHandler
{
private readonly DataRow _row;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "<Pending>")]
public RowCloneHandler(DataRow row)
{
_row = row ?? throw new ArgumentNullException(nameof(row));
if (row.RowState.Equals(DataRowState.Detached)) throw new ArgumentException("The rowState is detached.");
}
public DataSet CloneToDataSet()
{
var ClonedDataset = new DataSet { Locale = CultureInfo.InvariantCulture };
DataTable clonedMainTable = _row.Table.Clone();
ClonedDataset.Tables.Add(clonedMainTable);
ClonedDataset.Tables[_row.Table.TableName].ImportRow(_row);
CloneParentTablesToDataset(ClonedDataset, clonedMainTable);
CloneChildTablesToDataSet(ClonedDataset, clonedMainTable);
return ClonedDataset;
}
private void CloneChildTablesToDataSet(DataSet clonedDataset, DataTable clonedMainTable)
{
foreach (DataRelation dataRelation in _row.Table.ChildRelations)
{
DataTable childTable = dataRelation.ChildTable;
// clone the parent table
DataTable clonedChildTable = childTable.Clone();
// copy the parent rows related only to the passed row
foreach (DataRow childRow in _row.GetChildRows(dataRelation.RelationName))
{
clonedChildTable.ImportRow(childRow);
}
clonedDataset.Tables.Add(clonedChildTable);
DataColumn parentColumn = clonedMainTable.Columns[dataRelation.ParentColumns[0].ColumnName];
DataColumn childColumn = clonedChildTable.Columns[dataRelation.ChildColumns[0].ColumnName];
clonedDataset.Relations.Add(dataRelation.RelationName, parentColumn, childColumn, false);
}
}
private void CloneParentTablesToDataset(DataSet clonedDataset, DataTable clonedMainTable)
{
foreach (DataRelation parentRelation in _row.Table.ParentRelations)
{
DataTable parentTable = parentRelation.ParentTable;
// clone the parent table
DataTable clonedParentTable = parentTable.Clone();
// copy the parent rows related only to the passed row
DataRow parentRow = _row.GetParentRow(parentRelation.RelationName);
clonedParentTable.ImportRow(parentRow);
clonedDataset.Tables.Add(clonedParentTable);
DataColumn parentColumn = clonedParentTable.Columns[parentRelation.ParentColumns[0].ColumnName];
DataColumn childColumn = clonedMainTable.Columns[parentRelation.ChildColumns[0].ColumnName];
clonedDataset.Relations.Add(parentRelation.RelationName, parentColumn, childColumn, false);
}
}
}
You need to create a clone of your DataTable, import the DataRow to the cloned DataTable, and then add the computed column in the cloned DataTable. Here are some extension methods that do exactly that.
Update: I revised the code to take into account the existing relations with other tables. The code became much more complicated because now the cloned table must be placed inside the existing DataSet, and the existing relations must be also cloned, and temporary renamed. The cloned relations are created without constraints, so hopefully the performance will not be negatively affected.
public static class DataRowExtensions
{
public static object Compute(this DataRow dataRow, string expression)
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(object), expression);
return clonedRow[dataColumn];
}
}
public static T Compute<T>(this DataRow dataRow, string expression)
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(T), expression);
return clonedRow.Field<T>(dataColumn);
}
}
public static T? ComputeNullable<T>(this DataRow dataRow, string expression)
where T : struct
{
using (var clonedDT = CloneDataTable(dataRow))
{
clonedDT.ImportRow(dataRow);
var clonedRow = clonedDT.Rows[0];
var dataColumn = clonedDT.Columns.Add(null, typeof(T), expression);
return clonedRow.Field<T?>(dataColumn);
}
}
private static DataTable CloneDataTable(DataRow dataRow)
{
var dataTable = dataRow.Table;
var dataSet = dataRow.Table.DataSet;
if (dataSet == null) return dataTable.Clone();
var clonedDT = dataSet.Tables.Add();
foreach (DataColumn column in dataTable.Columns)
{
clonedDT.Columns.Add(column.ColumnName, column.DataType);
}
var relationsAdded = new List<
(DataRelation Cloned, DataRelation Original)>();
foreach (var relation in dataTable.ParentRelations
.Cast<DataRelation>().ToArray())
{
var relationName = relation.RelationName;
relation.RelationName = Guid.NewGuid().ToString();
var clonedColumns = relation.ChildColumns
.Select(c => clonedDT.Columns[c.ColumnName]).ToArray();
var clonedRelation = dataSet.Relations.Add(relationName,
relation.ParentColumns, clonedColumns, createConstraints: false);
relationsAdded.Add((clonedRelation, relation));
}
foreach (var relation in dataTable.ChildRelations
.Cast<DataRelation>().ToArray())
{
var relationName = relation.RelationName;
relation.RelationName = Guid.NewGuid().ToString();
var clonedColumns = relation.ParentColumns
.Select(c => clonedDT.Columns[c.ColumnName]).ToArray();
var clonedRelation = dataSet.Relations.Add(relationName,
clonedColumns, relation.ChildColumns, createConstraints: false);
relationsAdded.Add((clonedRelation, relation));
}
clonedDT.Disposed += (s, e) => // Cleanup
{
clonedDT.Rows.Clear();
foreach (var entry in relationsAdded)
{
dataSet.Relations.Remove(entry.Cloned);
entry.Original.RelationName = entry.Cloned.RelationName;
}
clonedDT.Columns.Clear();
dataSet.Tables.Remove(clonedDT);
};
return clonedDT;
}
}
Usage example:
var dt = new DataTable();
dt.Columns.Add("Price", typeof(decimal));
dt.Rows.Add(10);
decimal doublePrice = dt.Rows[0].Compute<decimal>("Price * 2");
Console.WriteLine(doublePrice);
Output:
20
I am new to C# and gone through lot of questions in Stackoverflow.com and didn't find the solution for my requirement. So finally posting here.
My requirement is to create the dynamic properties from datatable column names and set the values to dynamic properties from datatable. and finally bind the data to gridview.
So I decided to follow below steps to achieve this functionality( kindly Correct me If I am wrong)
my datatable contains 26 rows and 10 columns of data
Create a Class A
Add dynamic properties to A from datatable(column names)
Set values to properties of A
Make class A to List of A
Bind List of A to GridView
I have done the below steps
1.
[Serializable]
public class A
{
public A()
{
}
}
2 & 3.
DataTable dt = getData();
dynamic expando = new ExpandoObject();
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn col in dt.Columns)
{
var expandoDict = expando as IDictionary<String, Object>;
if (expandoDict.ContainsKey(col.ToString()))
expandoDict[col.ToString()] = row[col.ColumnName].ToString();
else
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
}
After executing the above for loop, "expando" object contains only last row of datatable.
Can you please help me how to fix the steps 2 to 5.
From what I understand, this code may be more what you are looking for. This should get the data into the expandoList for you. You will then need to handle the binding to the GridView.
DataTable dt = getData();
List<dynamic> expandoList = new List<dynamic>();
foreach (DataRow row in dt.Rows)
{
//create a new ExpandoObject() at each row
var expandoDict = new ExpandoObject() as IDictionary<String, Object>;
foreach (DataColumn col in dt.Columns)
{
//put every column of this row into the new dictionary
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
//add this "row" to the list
expandoList.Add(expandoDict);
}
Here's an extension method that would convert your datatable to list of Dynamic objects:
public static class DataTableExtension
{
public static IEnumerable<dynamic> AsDynamicEnumerable(this DataTable table)
{
// Validate argument here..
return table.AsEnumerable().Select(row => new DynamicRow(row));
}
private sealed class DynamicRow : DynamicObject
{
private readonly DataRow _row;
internal DynamicRow(DataRow row) { _row = row; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var retVal = _row.Table.Columns.Contains(binder.Name);
result = retVal ? _row[binder.Name] : null;
return retVal;
}
}
}
Usage: IEnumerable<dynamic> result = getData().AsEnumerable();
What's the equivalent in .NET to convert my DataGrid to a DataTable (DataGrid.ItemsSource isn't defined in .Net csharp.
Thanks!
DataTable dt = new DataTable();
dt = ((DataView)DataGrid1.ItemsSource).ToTable();
EDIT
This isn't a duplicate since the previous code is for WPF and I'm looking for an asp.net mvc csharp answer.
The ItemsSource is for WPF. Use the DataSource and cast it to DataTable like this:
dt = (DataTable)DataGrid1.DataSource;
EDIT: And if you get into trouble with above approach, you can use a custom method like this:
private DataTable ToDataTable(DataGridView dataGridView)
{
var dt = new DataTable();
foreach (DataGridViewColumn dataGridViewColumn in dataGridView.Columns)
{
if (dataGridViewColumn.Visible)
{
dt.Columns.Add();
}
}
var cell = new object[dataGridView.Columns.Count];
foreach (DataGridViewRow dataGridViewRow in dataGridView.Rows)
{
for (int i = 0; i < dataGridViewRow.Cells.Count; i++)
{
cell[i] = dataGridViewRow.Cells[i].Value;
}
dt.Rows.Add(cell);
}
return dt;
}
And then use it:
var dataTable = ToDataTable(dataGridView1);
Also MoreLinq is a good choice in case the type of Datasource is a list. Check this solution to know how to use it: https://stackoverflow.com/a/42550827/2946329
If you are referring to the System.Windows.Forms.DataGrid or System.Web.UI.WebControls.DataGrid, then the best way would be to cast the Datasource property to a DataTable.
Of course the Datasource property has to actually be a DataTable underlying type to begin with. You need to know the underlying type of the object stored in the Datasource property.
If the underlying type of Datasource is a generic list, then this SO post should help: How to convert a list into data table
FYI - The Windows Forms DataGrid control, according to Microsoft, has been replaced by the DataGridView.
if there is visible columns in datagridview you can use
private DataTable ToDataTable(DataGridView dataGridView)
{
var dt = new DataTable();
int columnCount = 0;
List<int> columnNumbers= new List<int>();
foreach (DataGridViewColumn dataGridViewColumn in dataGridView.Columns)
{
if (dataGridViewColumn.Visible)
{
dt.Columns.Add(dataGridViewColumn.Name);
columnNumbers.Add(columnCount);
}
columnCount++;
}
var cell = new object[columnNumbers.Count];
foreach (DataGridViewRow dataGridViewRow in dataGridView.Rows)
{
int i = 0;
foreach (int a in columnNumbers)
{
cell[i] = dataGridViewRow.Cells[a].Value;
i++;
}
dt.Rows.Add(cell);
}
return dt;
}
The custom method does not take into account the hidden columns. You are getting an error, because you have too many cells for the columns copied.
You can use :
int dgv1RowCount = dgv1.Rows.Count;
int numOfColumns = dgv1.Columns.GetColumnCount(DataGridViewElementStates.Visible) ;
int numCells = dgv1RowCount * numOfColumns;
// use numCells in the for loop
for (int i = 0; i < numOfCells ; i++)
{
enter code here
}
I am new to C#. I have rfc that returns data from SAP system as nested structure but when I'am fetching that data using:
IrfcTable table = rfc.getTable("exporting_parameter"); // et_customer
it returns only first inner structure only.
For example my exporting internal table for rfc is
et_customer that contains sub structure as follow:
gen_data
bank data
tax data
it returns value inside gen_data only.
How to get entire data?
A couple of Extensions that may help. eg Convert from SAP structures to Other better known structures.
public static class SapToDataExtensionClass
{
public static Dictionary<string,string> ToDictionary(this IRfcStructure stru)
{
Dictionary<string,string> dict = new Dictionary<string, string>();
for (int i = 0; i < stru.Metadata.FieldCount; i++)
{
dict.Add(stru.Metadata[i].Name , stru.GetString(i) );
}
return dict;
}
public static DataTable GetDataTable(this IRfcTable i_Table)
{
DataTable dt = new DataTable();
dt.GetColumnsFromSapTable(i_Table);
dt.FillRowsFromSapTable(i_Table);
return dt;
}
public static void FillRowsFromSapTable(this DataTable i_DataTable, IRfcTable i_Table)
{
foreach (IRfcStructure tableRow in i_Table)
{
DataRow dr = i_DataTable.NewRow();
dr.ItemArray = tableRow.Select(structField => structField.GetValue()).ToArray();
i_DataTable.Rows.Add(dr);
}
}
public static void GetColumnsFromSapTable(this DataTable i_DataTable, IRfcTable i_SapTable)
{
var DataColumnsArr = i_SapTable.Metadata.LineType.CreateStructure().ToList().Select
(structField => new DataColumn(structField.Metadata.Name)).ToArray();
i_DataTable.Columns.AddRange(DataColumnsArr);
}
}
I created custom datatype classes that format the data the way I need it. The data I retrieve from the database comes as .NET base types, so I need to loop through the DataTable, convert each item into it's custom type, and put the converted item into a new table. I also copy the column names from the old table to the new one. The problem is, when I bind a GridView to my new table, it throws an exception:
HttpException:
The data source for GridView with id 'TestGrid' did not have any properties
or attributes from which to generate columns. Ensure that your data source
has content.
Stack Trace:
at System.Web.UI.WebControls.GridView.CreateAutoGeneratedColumns(PagedDataSource dataSource)
at System.Web.UI.WebControls.GridView.CreateColumns(PagedDataSource dataSource, Boolean useDataSource)
at System.Web.UI.WebControls.GridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.GridView.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
at System.Web.UI.WebControls.GridView.DataBind()
What do I need to add to my DataTable to get autogeneratecolumns to work?
Edit: Here is the code for the DataTable:
// Populate first DataTable with data from database.
adapter = new DataAdapter("SELECT status, date_ordered, date_due FROM import_table", OpenConnection);
DataTable originalTable = new DataTable();
adapter.Fill(originalTable)
// Second DataTable for converted table data.
DataTable convertedTable = new DataTable();
// The list of custom datatypes to convert to.
Type[] newTypes = {typeof(TrackingStatus), typeof(Date), typeof(Date)};
// Set the ColumnName and DataType on each column of the new table.
for(int i = 0; i < originalTable.Columns.Count; i++)
{
convertedTable.Columns.Add();
convertedTable.Columns[i].ColumnName = originalTable.Columns[i].ColumnName;
if(newTypes.Length > i)
convertedTable.Columns[i].DataType = newTypes[i];
}
// Convert each item from the old table and add it to the new table.
foreach(DataRow oldRow in originalTable.Rows)
{
DataRow newRow = convertedTable.NewRow();
for(int i = 0; i < convertedTable.Columns.Count; i++)
{
if(newTypes.Length <= i)
newRow[i] = oldRow[i];
else if(newTypes[i] == typeof(Date))
newRow[i] = Date.FromObject(oldRow[i]);
else if(newTypes[i] == typeof(TrackingStatus))
newRow[i] = TrackingStatus.FromObject(oldRow[i]);
else if(newTypes[i] == typeof(EmailAddress))
newRow[i] = EmailAddress.FromObject(oldRow[i]);
}
convertedTable.Rows.Add(newRow);
}
// Bind the GridView.
displayGrid.DataSource = convertedTable;
displayGrid.DataBind();
Instead of creating a new datatable when you convert each to custom types, create a new List and bind the list to the datasource. e.g.
var list = new List<MyClass>();
var myType = //Convert your type
list.Add(myType);
grid.DataSource = list;
And ofcourse this all is just an idea of how to do it.
UPDATE:
Saw your code afterwards:
Try this:
Create a class called ImportRow
class ImportRow
{
private string m_Status = string.Empty;
private DateTime m_DateOrdered;
private DateTime m_DateDue;
public ImportRow() { }
public string Status
{
get { return m_Status; }
set { m_Status = value; }
}
public DateTime DateOrdered
{
get { return m_DateOrdered; }
set { m_DateOrdered = value; }
}
public DateTime DateDue
{
get { return m_DateDue; }
set { m_DateDue = value; }
}
}
Then use it as:
var importedData = new List<ImportRow>();
foreach (DataRow oldRow in originalTable.Rows)
{
var newRow = new ImportRow();
newRow.Status = oldRow["status"].ToString();
newRow.DateDue = Convert.ToDateTime(oldRow["date_due"].ToString());
newRow.DateOrdered = Convert.ToDateTime(oldRow["date_ordered"].ToString());
importedData.Add(newRow);
}
Then
displayGrid.DataSource = importedData;
displayGrid.DataBind();
Your custom type needs public properties like these:
public class Foo
{
public int Id;
public string Name;
}
or you need to use the DataTable itself as DataSource.