If I use ds.Tables[0].Rows.Count, I get the row count regardless of if the rows have data in them, I do not want to count the rows that empty, whitespace or null, is there any way to do it actually without reading row by row?
if you manage to isolate the rows you want with a filter you can use any of these approaches:
DataView myView = new DataVie(ds.Tables[0]);
myView.RowFilter = "NAME IS NOT NULL";
int count = myView.Count;
or also with Select...
DataRow[] myRows = ds.Tables[0].Select("NAME IS NOT NULL");
int count = myRows.Length;
then in the first case you can iterate on the DataView and in the second case you iterate on the DataRow array. For binding to UI Controls DataView is probably better.
yes- DataTable implements the IEnumerable interface, which means that you can use LINQ to query it:
ds.Tables[0].Count(row => !string.IsNullOrEmpty(row["Name"]) /*etc..*/);
(if you don't already know linq- you should familiarize yourself. it's great.)
Related
I am creating a WPF application. There is a DataGrid displaying my items and search bar to filter the data. As you know we can't have specific rows from a Dataable to be referenced from another datatable. So the way I'm filtering right now is cloning my original database and adding the rows which matches search bar text to the cloned datatable. After that setting the datagrid's ItemsSource to the cloned datatable to show the filtered rows.
Now the problem is that when I edit my datagrid with filtered rows then obviously that cloned datatable is being modified not the original datatable. So how can I make those changes in the original datatable as well ?
I tried referencing rows from original datatable but that's no possible as one DataRow in memory can have only one container, the original datatable in this case.
EDIT
The answer was simple instead of using 2 DataTable use a DataView which is designed for this very purpose. See the modified code below.
My filter logic:
var filteredTable = dt.Clone();
foreach( DataRow row in dt.Rows)
{
if(row[FilterCategory].ToString().StartsWith(txtb_search.Text))
{
filteredTable.Rows.Add(row.ItemArray);
}
}
ItemsGrid.ItemsSource = filteredTable.DefaultView;
Here is how to do filtering the correct way using DataView. The filter string can have many forms depending on the requirement. sortColumn is filterColumn right now but can be any column to base sort on. Here is a quick tutorial to all this: http://www.csharp-examples.net/dataview-rowfilter/
string filterColumn = dt.Columns[columnIndex].ToString();
string filter = filterColumn + " LIKE '" + txtb_search.Text + "*'";
DataView dv = new DataView(dt, filter, sortColumn , DataViewRowState.CurrentRows);
ItemsGrid.ItemsSource = dv;
I want to use the user-selected rows from one DataGridView as the DataSource for a second DataGridView. Note both DataGridViews will have identical columns.
Obviously I can iterate over the selected rows, obtain the key values, and re-query the database for a List to use as the DataSource of the 2nd grid, but that seems lame.
Surely there is an elegant way of simply re-using the SelectedRows collection as a DataSource?
You cannot directly set collection of DataRow as datasource, you can read more details from MSDN
How about doing (bit) traditional way?
var dt = ((DataTable)dataGrid1.DataSource).Clone();
foreach (DataGridViewRow row in dataGrid1.SelectedRows)
{
dt.ImportRow(((DataTable)dataGrid1.DataSource).Rows[row.Index]);
}
dt.AcceptChanges();
dataGrid2.DataSource = dt;
Another way to do this using CopyToDataTable method.
DataTable dtable2;
DataRow[] rowArray = dataGridView1.SelectedRows;
If !(rowArray.Length == 0 )
{
dTable2 = rowArray.CopyToDataTable();
}
dataGrodView2.DataSource = dTable2;
Thanks for your replies. Seems there isn't a very simple way.
I did it this way:
MyDatGridView.SelectedRows.Cast<DataGridViewRow>().Select(dgvr => (int)dgvr.Cells[0].Value).ToList());
Then I tried to use the resulting List with a .Contains in a .Where clause.
I have a filtered data view, from which I have to extract the values. Problem is that when I do this, I am getting the values from non filtered data also.
dv1.RowFilter = "collegeno=" +i;
for(int k=1;k<dv1.count;k++)
{
//inserting data in database; there is column in database table; I am inserting into it;
dv1.Table.Rows[k]["roomno"]);
}
For ex: The total no. of rows in DataView is 200;
When i=1 I have 30 records;
If I supply k=4, then I should get fourth row from this 30 records.
But I am getting 4th row of the 200 records..
The code you have written is accessing the main table using the code block dv1.Table.
Instead try as this
dv1[k]["roomno"]
This code works on DataView, on which the filter is applicable.
If you use DataView.Table then it will access the non-filtered results.
Reference Link: MSDN - DataView.RowFilter
If I supply k=4, then I should get fourth row from this 30 records.
But I am getting 4th row of the 200 records..
That's because you're querying the table, not the view. Instead you should do this:
dv1.RowFilter = "collegeno=" +i;
object value = dv1[k]["roomno"];
Depending on what you need, you might want to use the DataTable.Select method instead of a DataView:
var rows = table.Select("collegeno=" +i);
object value = rows[k]["roomno"];
DataTable dt = dv.ToTable();
for(int k=1;k<dt.Rows.Count;k++)
{
dt.Rows[k]["roomno"];
//dv1.Table.Rows[k]["roomno"]);
}
What's the most efficient way of filtering DataRows in a DataTable? I have a list of integers and want to retrieve all rows (and eventually create a DataTable from them) which match the integers in the list. I'm currently using the code below, but it's quite slow. Am I missing a more efficient way?
foreach (var i in integerlist)
{
DataRow dr = (from row in originalDataTable.AsEnumerable()
where row.Field<int>("urlID") == i
select row).FirstOrDefault<DataRow>();
if (dr!= null)
{
newDataTable.Rows.Add(dr);
}
}
I suggest you to try to do vice versa.
foreach (var row in originalDataTable)
{
if(integerList.Contains( (int)row["urlID"]))
newDataTable.ImportRow(row)
}
It makes even more sense if you have more rows in dataset then integers in your int collection.
Hope it helps :)
Hm... may be I'm missing something, but...
Woudn't be it easier just use DataView and apply a RowFilter for it ?
you could try doing a join such as:
var resultSet =
from row in originalDataTable.AsEnumerable()
join i in integerlist
on row.Field<int>("urlID") equals i
select row;
that should give you the full result set.
if you need a datatable you could do:
resultSet.CopyToDataTable();
As #Tigran says you can use the dataview, check this msdn article on how to accomplish just that.
Basically you use a DataView to filter the data and the you call the DataView.ToTable method to get the new DataTable.
I have a DataTable available with me which contains thousands of rows. There is a column called EmpID which is containing '0' for some of the rows. I want to remove them from my current DataTable and want to create a new correct DataTable. I cannot go row by row checking it since it contains huge amount of data. Give me a suggestion to overcome this problem.
the best way would be to filter it at source (if possible) - so if you are creating it from a db, exclude all 0 values in your sql query itself using a where
starting .net 2.0, ms enhanced the filtering logic on the datatable to a great extent. so if you used the dataview (on top of your datatable) and added the where clause in there and added some sort of runtime indexes on this field, it would give you the desired results without looping over all records
You can use DataTable.Select("EmpID <> 0"). This will return an array of DataRows which you can create your new DataTable from if required.
Isn't it possible to first select the rows with EmpID = 0 and then iterate over these only ?
DataTable newTable = new DataTable();
foreach (DataRow dr in oldTable.Select("EmpID = '0'")) {
newTable.Rows.Add(dr);
oldTable.Rows.Remove(dr);
}
You can try
DataRow[] temp=
table.Select("EmpID ='0'");
foreach(DataRow dr in temp)
{
table.Rows.Remove(dr);
}
table.acceptchanges();