I need to create a DataView from a DataTable, but with an unusual twist:
I need to decide (with code) on a row-by-row basis which rows in the DataTable are included in the DataView.
DataTable dt = LoadData();
DataView dv = new DataView(dt);
foreach (DataRow row in dt.Rows)
{
if (RowIsGood(row))
{
// This obviously doesn't work but I need equivalent logic:
DataRowView drv = new DataRowView();
drv.Row = row;
dv.Add(drv);
}
}
Some important things to note:
The code in the RowIsGood function above is too complicated to replicate using the standard RowFilter method.
The DataTable has the potential to be very large. It is also referenced by multiple grid controls. Adding temporary columns to the DataTable to facilitate a RowFilter operation is not possible.
I'm using .NET v4.0.
Is then even possible with the DataTable/DataView architecture?
Does LINQ allow me to customize a DataView like I need?
Thanks in advance!
Since you are looking for a row by row solution and already have a function that takes a DataRow and returns a bool.
Simply add the refernce to System.Data.DataSetExtensions
And use the AsDataView Method
DataView dv=DT.AsEnumerable().Where(RowIsGood).AsDataView();
DataView dv = (from n in DT.AsEnumerable() Where RowIsGood(n) select n ).AsDataView();
Related
One DataSet usually has lots of DataTable, but I'm only to target a particular DataTable which I thought it's pretty normal but apparently failed to do it?
Below were the approaches I've tried:
//Could not find an implementation of the query pattern for source type.......
DataTable dt = from table in changesDataSet.Tables
where table.TableName = "ABC"
select table;
//Surprisingly there was no method "Where" in changesDataSet.Tables
DataTable dt = changesDataSet.Tables.Where(x=>x.TableName="ABC").First();
Below was the code that able to print each and every table. I know I can do it via a loop but please tell me loop isn't the only options
foreach(DataTable table in changesDataSet.Tables)
{
Console.WriteLine(table.TableName);
}
You can access the table using an indexer on the collection of tables (DataTableCollection):
DataTable dt = changesDataSet.Tables["ABC"];
I have a DataGridView which I have used RowFilter on it like following:
(dgv.DataSource as DataTable).DefaultView.RowFilter = whereClause;
Before applying the RowFilter the DataGridView has 1087 records and afterwards, it has about 8.
Now I want to work on those 8 records.
How can I access them?
If you do
dgv.DataSource as DataTable
Then you can do the following
dataTable dt = dgv.DataSource as DataTable;
DataRow[] rows = dt.Select("your filter goes here");
You can do same thing by Linq if you want to. These are your rows and you can work with them. And to Edit only these records do:
DataGridView.DataSource = rows;
Also, you can create a custom DataView, which will filter records the way you want it, and set datasource to that view. But remember, the key here, no matter how many views you have - this is same dataTable that you looking at
DataView view = new DataView();
view.Table = dt;
view.RowFilter = "your filter";
view.Sort = "your sort";
You can use DataGridViewRow.DataBoundItem to access to the underlying data.
If your DataGridView bound to the DataView the underlying data is of type DataRowView. You can use code like this:
var dataRow = dgv.Rows[rowIndex].DataBoundItem as DataRowView;
I have a DataView with Sort applied on it. I am not able to assign/copy the Sorted State of DataView to DataTable.
Sort the DataView with Column 'Distance':
DataTable table=GetData();
DataView view = table.DefaultView;
view.Sort = "Distance";
this works fine.
But, when i assign this DataView to DataTable it *LOOSES THE SORTED STATE*.
DataTable dt = (view.Table);
This looses the Sorted State of DataView
Any idea?
Please correct my code if something wrong.
So, i want to assign/copy the Sorted DataView to DataTable without loosing the Sorted State.
Use view.ToTable() instead of view.Table. Please see below snippet
DataTable table=GetData();
DataView view = table.DefaultView;
view.Sort = "Distance";
DataTable dt = view.ToTable();
You can directly get dataview propery in the Datatable itself.
DataTable table=GetData();
table.DefaultView.Sort="Distance";
table=table.DefaultView.ToTable();
Here's a really efficient way to write a one line sort that maintains the sorting of the DataView in the parent DataTable.
table = new DataView(table, "", "Distance",
DataViewRowState.CurrentRows).ToTable()
I am showing a DataGridView control on my form, populating it with a DataTable object through the DataSource property of the control. I set the control to select the entire row when it is selected, and enabled multiselect. All of this works swimmingly.
A user can select multiple rows and click a button. I want to make a new DataTable object with copies of the selected rows and pass that to a Crystal Report.
Is there an efficient means of doing this? It seems the only way is to parse the new rows for the new DataTable from the selected grid cells, which strikes me as relatively ridiculous.
This is my solution to the question "How to get selected Rows as DataTable":
copy structure of original DataTable
copy each row (as a row may exist only in one datatable object)
DataTable selectedRows = (sourceDataGridView.DataSource as DataTable).Clone();
foreach(DataGridViewRow row in sourceDataGridView.SelectedRows) {
selectedRows.Rows.Add((row.DataBoundItem as DataRowView).Row.ItemArray);
}
I've found that the best way to avoid iterating over the DataTable to find the rows you want is to bind to a DataView instead. This way, you can sort and all that other fun stuff you like to do with a DataGridView, and can still get the data you need without manually parsing the underlying DataTable.
Below is a succinct example that should show you everything you need to get a DataRow without searching:
DataGridView dataGridView1 = new DataGridView();
DataTable tb = new DataTable();
DataView dv = tb.AsDataView();
dataGridView1.DataSource = dv;
// Get the row indexes in whatever your favorite manner is.
List<int> selectedRowIndexes = YourGetSelectedRowIndexesMethod();
foreach(int selectedRowIndex in selectedRowIndexes)
DataRow dr = dv[selectedRowIndex].Row;
One quick method to get the selected indexes (just in case you need it):
List<int> indexes = new List<int>();
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
indexes.Add(row.Index);
}
Is there anyway of filtering datatable based on other datatable. something like below:
foreach (datarow dr in somedatatable.select("id= someothertable.rows["someotherid"])
{
dr[somefield]=someothertable[someotherfield];
}
You can do a ordinary SQL select using DataView
DataView dv = new DataView(dataTableToFilter);
dv.RowFilter = ""//SQL condition
Complete useful example in your case you can find here:
Creating a DataTable from a DataView
Where you apply a DataView filter to a DataTable and create a new DataTable from filtered rows.
I have a question, why you want to do the filter logic in your code? Your example logic is very simple.
I order to do filter more efficient, we'd like use database to do that. I think your requirement can be implemented by using a join statement. Do you agree?