Clear Sorting from DataView - c#

I have a dataview. Source of dataview is a view from sql server.
Dataview is sorted. Like this:
dv_building.Sort = "bld_number"
this dataview is a datasource to my datagird1:
DataGrid1.DataSource = dv_building
Now I want to remove sorting dv_building.Sort = String.Empty but the view of my data grid was changed, because sorting was removed, ie dataview was returned to their default sorting, probably by clustered index.
How can I remove sorting, but the actual sorting remain by bld_number? Is it possible?

I found this workaround to achieve requested behaviour: implementation of class derived from Datatable is accessible for me, additional column appended to Columns:
Columns.AddRange(
new DataColumn[N]
{
...
new DataColumn("Order", typeof (int))
}
I enumerate this column with order numbers after each data view column modification (column participated in sort). When I need freeze sorting I switch DataView.Sort property to this "Order" column. To unfreeze - dataView.Sort = regularSortCriterion.

Related

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;

DataView Sorting After AddNew

I am trying to add an initial unbound entry into a bound ComboBox. I am trying an approach very similar to the answer to the following post:
How to insert 'Empty' field in ComboBox bound to DataTable
However, the main difference is that I have strict requirements and cannot add a row to the actual datatable (as this is used by other components). So, my solution is to add the additional row to the dataview instead of the datatable:
public void FillVendorComboBox(DataSet1.VendorDataTable vendors)
{
//Create a custom view of the vendor table
DataView view = new DataView(vendors);
//Add a new row to the view with default values
DataSet1.VendorRow vendorRow = (DataSet1.VendorRow)view.AddNew().Row;
vendorRow.Name = "a";
//Sort the view according to the vendor name
view.Sort = vendors.NameColumn.ColumnName;
//Bind the view to the combo box
cbxVendor.DataSource = view;
cbxVendor.DisplayMember = vendors.NameColumn.ColumnName;
cbxVendor.ValueMember = vendors.IdColumn.ColumnName;
}
The problem is that the sorting is not working as expected. The added value is always sorted to the end of the ComboBox:
BC (bound)
Shell (bound)
a (added) <-- why is this sorting to the bottom?
Also please note that the VendorRow.Name is datatype System.String and VendorRow.Id is datatype System.Int32.

Dataset row number w/ filled rows only

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.)

Create ADO.NET DataView showing only selected Columns

In C# & .NET, can one create a DataView that includes only a proper subset of the DataColumns of a given DataTable?
In terms of relational algebra, one assigns a RowFilter in order to perform a "selection" operation (σ). How would one perform a "projection" operation (π)?
You can't do that, but you can create a copy of the table with only the columns you want :
DataView view = new DataView(table);
DataTable table2 = view.ToTable(false, "FirstColumn", "SecondColumn", "ThirdColumn");
Optionally you can return rows that have distinct values for the selected columns :
DataView view = new DataView(table);
DataTable table2 = view.ToTable(true, "FirstColumn", "SecondColumn", "ThirdColumn");
Well I can't see any reason for "wanting" to do that... Remember, a DataView is just a list of pointers to the rows in the original table, and there is obviously no way to remove columns from the the original table... at least not without affecting every other function utilizing that table... Just only use the columns you want...
create dataview as a swap from one table to other table, and use the dtswap as datasource.
DataView dw = new DataView(dtfee);
DataTable dtswap = new DataTable();
dtswap = dw.ToTable(true,"Fees", "FeeAmount", "Year", "CollectorName", "Month");
DataSet and its associated types have no ability to perform relational operations.

Categories