Sort and Search Datatable - c#

I have a datatable that has been bound to a Gridview in code behind. This means i would have to sort columns in code behind and when searching for a record i would imagine that would be done in code behind too.
The code i have to sort the gridview is
Private Function GetCustData As Datatable
Dim dt as new datatable
dt = GetDataFromBusinessLayer(CustomerID)
Return dt
End Function
And the code to sort
Private Sub gv_Sorting(sender As Object, e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gv.Sorting
If e.SortExpression = "Name"
gv.DataSource = GetCustData '.DefaultView.Sort = "Name" & "DESC"
gv.DataBind()
End If
End Sub
As you can tell i tried using .DefaultView.Sort = "Name" & "DESC" but this didnt work and got the error Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource. Searching around most are using Viewstate but that doesnt seem applicable in my case.
Can anyone advise how i would sort one/multiple columns?
In addition i will like to have a textbox which will search for the Name column. I think the above should suffice when it comes to it but if not could someone put me on the right track so i can work towards that now rather than having to change what im doing at a later stage?

First of all, your current code does not have a space. To sort by Name DESC your Sort string would need to be: "Name DESC".
To set the Sort string to multiple columns, just add a comma between each one, like this:
Dim dt as new datatable = GetCustData(1)
dt.DefaultView.Sort = "Name DESC, FirstName ASC"
gv.DataSource = dt.DefaultView
gv.DataBind()

I think you can create a list of rows
List<DataRow> list = dt.AsEnumerable().ToList();
and then when you have a list you can now use sort
list.OrederBy(c=>c.///specific value in your list)

What about using Linq to do the sort for you.
Dim dt as new datatable
dt = From dr as Datarow in GetDataFromBusinessLayer(CustomerID)
Order by dr.item("First Sort field), dr.Item("Second Sort Field")
Select dr
Return dt
... I did this without the IDE, but that should do the trick, I believe.
Here's one exmaple online - Sorting DataTable with Linq
Hope this helps.

Related

Having a DataTable as a cell value of another DataTable in WPF

so my problem is that I want to display a table inside another table in WPF.
I use a DataTable in order to display some data and there is one column, in which I need to display another DataTable. I set AutoGenerateColumns="True". For a little testing, this is what I wrote (well, it works as expected):
var curDataTable = new DataTable();
curDataTable.Columns.Add("name" , typeof(string));
curDataTable.Columns.Add("number", typeof(int));
DataRow curRowData = curDataTable.NewRow();
curRowData[0] = "jones";
curRowData[1] = 90;
curDataTable.Rows.Add(curRowData);
Now, let's say I already have a filled DataTable _dataTable. I now want to display this _dataTable in my second column. This is what i would expect to work, but what does not work:
var curDataTable = new DataTable();
curDataTable.Columns.Add("name" , typeof(string));
curDataTable.Columns.Add("table", typeof(DataTable));
DataRow curRowData = curDataTable.NewRow();
curRowData[0] = "jones";
curRowData[1] = _dataTable;
curDataTable.Rows.Add(curRowData);
Has anyone an idea how to fix this?
Using nested DataTables won't work.
What you should do is to replace the outer DataTable with a custom type and bind to a custom collection property of this type in a DataGridTemplateColumn.
I don't think that nested DataTables are possible...
What you can do is create new column in '_datatable' with the name of "name"
_datatable.Columns.Add("name" , typeof(string)).SetOrdinal(0);
Using SetOrdinal(0) you can make "name" column first column. Now you maybe able to add new columns to it.
I hope it helps

DataTable Select & DataView Sort

Quick Question.
When I use a DataTable.Select("..") without a Sort condition after using a DataView to Sort the DataTable, should the records be returned in Sorted order ?
Using this method I find that in some cases the records aren't being returned in the correct order, it's hit and miss as well - sometimes they are sometimes they aren't.
If I specify a sort condition to the Select then it all works fine, but the performance implications are drastic for large DataTables.
I've tried using the DataView RowFilter to reduce the hitset but every time I change the RowFilter the performance goes south
MyDtable.Load(MyReader); // its am Oracle DataReader
MyView = new DataView(MYDtable);
MyView.Sort = "CODE, TABLE DESC";
DataRow[] MyRecs = MyDtable.Select("TABLE > 'FREDDO' AND CODE > '661991'");
The number of records returned is always correct, it's just the order that may vary (sometimes)
Thanks,
John
John,
Applying a sort order to a DataView does not change the underlying DataTable it represents. So your code snippet using both DataView properties and DataTable.Select() method will not work as you intended.
When sorting and filtering, you must choose which method is best for presenting and maintaining the data. Here are sorting and filtering usages examples for both DataTable and DataView.
Using DataTable
Syntax:
public System.Data.DataRow[] Select (string filterExpression, string sort);
Example:
DataRow[] MyRecs = MyDTable.Select("TABLE > 'FREDDO' AND CODE > '661991'", "CODE, TABLE DESC");
foreach (DataRow rec in MyRecs)
{ . . . . }
Reference: DataTable.Select() Method Reference
Using DataView
Example:
DataView MyView = new DataView(MyDTable);
MyView.Sort = "CODE, TABLE DESC";
MyView.RowFilter = "TABLE > 'FREDDO' AND CODE > '661991'";
Reference: DataView.RowFilter Property Reference
Note the link takes you to Microsoft’s RowFilter property reference page, the included example shows usage information for both RowFilter and Sort properties.
Or
Syntax:
public DataView (System.Data.DataTable table, string RowFilter, string Sort,
System.Data.DataViewRowState RowState);
Example:
DataView MyView = new DataView(
MyDTable,
"TABLE > 'FREDDO' AND CODE > '661991'",
"CODE, TABLE DESC",
DataViewRowState.CurrentRows);
foreach ( DataRowView rec in MyView )
{ . . . . }
Reference: DataView Class Constructor Reference
Both methods will return the data filtered and sorted correctly. The difference is in how the data is being returned. You must choose the method whose return object best suit your needs.

Correct way of filtering datagrid using datatables in C# WPF

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;

C# sort rows of dataTable using interface

Here is my code for how I get data from a database and add it to a DataTable named data,
I have to sort this all table by data of row "Spelionu skaicius" using interface (increasingly), but I have no idea how to realize that, can someone help with that?
i know there is a lotof ways to sort this, but i have to make this using interface.
using (FbConnection fbBD = new FbConnection(csb.ToString()))
{
fbBD.Open();
FbTransaction transact = fbBD.BeginTransaction();
FbCommand sqlReq =
new FbCommand("SELECT vardas,pavarde,sp_skaicius,spelioniu_sk FROM zaidejai WHERE atspetas='Taip'", fbBD, transact);
using (FbDataReader r = sqlReq.ExecuteReader())
{
while (r.Read())
{
DataRow rw = dt.NewRow();
rw["Vardas"] = r.GetString(0);
rw["Pavarde"] = r.GetString(1);
rw["Skaicius"] = r.GetValue(2);
rw["Spelionu skaicius"] = r.GetValue(3);
data.Rows.Add(rw);
}
}
transact.Commit();
fbBD.Close();
}
P.S. sorry for my English
use the datatable DefaultView property:
data.DefaultView.Sort = "Spelionu skaicius";
you can then work with data.DefaultView (a dataview) or if you need a datatable, you can do this:
data = data.DefaultView.ToTable();
<-- EDIT -->
The above is for regular sorting. If you want to use IComparable, you will have to use custom clases in stead of DataTable. Here's an explanation of how.
It's best if you let the database sort the data so instead, I would change your select to this:
SELECT vardas,pavarde,sp_skaicius,spelioniu_sk
FROM zaidejai
WHERE atspetas='Taip'
ORDER BY spelioniu_sk
Note that I used spelioniu_sk because that's the 4th column listed on your select which is then mapped to Spelionu skaicius in your datatable definition
If you still must sort the datatable after you've gotten the data from the database, perhaps in a different order, you can use the DataView propery of the DataTable as so:
data= data.DefaultView.Sort = "`Spelionu skaicius` ASC";
OR
data = data.DefaultView.Sort = "`Spelionu skaicius` DESC";
Depending on the order that you need to sort by.
Note: I am not sure whether the above Sort Expression will work fine. Since you have decided to name your column with a space in the middle, you may need to enclose the 2 words in either backquotes (as I did above) or maybe square brackets (eg [Spelionu skaicius] ASC)

How to remove rows from huge data table without iterating it?

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();

Categories