WPF BindingListCollectionView to ListCollectionView for DataTable as ItemsSource - datatable

I want to do custom sorting on a ListView which has a DataTable as ItemsSource:
myListView.ItemsSource = (data as DataTable);
And this are the first lines of my sorting function:
DataView view = (myListView.ItemsSource as DataTable).DefaultView;
ListCollectionView coll = (ListCollectionView)CollectionViewSource.GetDefaultView(view);
The second line throws an execption like:
Unable to cast "System.Windows.Data.BindingListCollectionView" to "System.Windows.Data.ListCollectionView"
Has anyone a solution? Thx 4 answers

It returns an ICollectionView that is not a ListCollectionView. You most likely want a view on top of a view to get the features that ListCollectionView has. And since ICollectionView implements CollectionChanged, you wouldn't want to use BindingListCollectionView.
DataView view = (myListView.ItemsSource as DataTable).DefaultView;
ListCollectionView coll = new ListCollectionView(CollectionViewSource.GetDefaultView(view));
Although an alternative would be:
DataView view = (myListView.ItemsSource as DataTable).DefaultView;
BindingListCollectionView coll = new BindingListCollectionView(view);
If you only wanted only one view.
If you are binding directly to a WPF control, it is best to bind directly to it without making a BindingListCollectionView/ListCollectionView, as DefaultView already allows sorting of the DataTable.
Binding binding = new Binding() { Source = (myListView.ItemsSource as DataTable) };
this.myListView.SetBinding(myListView.ItemsSourceProperty, binding);
DataView view = (myListView.ItemsSource as DataTable).DefaultView;
view.Sort = "Age";
Hopefully Helpful,
TamusJRoyce

Related

JavaFX8: Strings are not displayed in TableView

I have the following problem: I try to populate a tableview in JavaFX8 with an array. So, I try to add the array as a row to the tableview. I run this code in the Controller of my FXML file, when enter is pressed. This is the code:
String[] words = {"ace", "boom", "crew", "dog", "eon"};
List<String> tableViewRow = Arrays.asList(words);
ObservableList<String> row = FXCollections.observableList(tableViewRow); //observableArrayList also doesn't work
transactionOverview.getItems().add(row);
transactionOverview is my tableview, and the String[] is just a placeholder for my actual String[]. I tried to create my tableview in multiple ways:
public TableView<ObservableList<String>> transactionOverview;
public TableView<ObservableList> transactionOverview;
public TableView transactionOverview;
None of them works.
The problem is that tableview gets an extra row, which I can select, but there are now string values visible in the tableview. I don't know if they are added.
My code is based on Javafx 2.2 - Dynamic table view - table data (answer from Jitendra Pareek), and I have chosen for this solution because I don't want to use an extra class to populate my tableview.
Any help is appreciated!
Since (according to your comments) you have a fixed number of columns, I would strongly recommend creating a model class to hold the items in each row of the table. You can then follow the standard patterns and it should work readily.
However you manage a TableView, you must provide a cell value factory for each column. This is essentially a function that specifies how to get the value for a cell from the item in the row. If your use a model class that uses JavaFX properties, then you can use a PropertyValueFactory (though Java 8 lambda expressions make that pretty much redundant). Otherwise, you need to implement a callback.
If you really want to use a list structure to hold the data for each row, and assuming your table and table columns are all defined in the FXML file, you would do something like this in your controller class:
#FXML
private TableView<ObservableList<String>> transactionOverview ;
// ...
public void initialize() {
for (int i=0; i < transactionOverview.getColumns().size(); i++) {
TableColumn<ObservableList<String>, String> col = transactionOverview.getColumns().get(i);
final int colIndex = i ;
col.setCellValueFactory( (CellDataFeatures cellData) -> {
ObservableList<String> rowData = cellData.getValue();
return new ReadOnlyStringWrapper(rowData.get(colIndex));
});
}
// ...
}

MVC3 Razor Passing ViewModel to Conroller List<> is null

I have a MVC 3 applicaiton in which I pass a vewmodel from the controller to the view. The vewmodel contains a couple of List<> properties.
public ActionResult MainView()
{
var model = GetViewModel();
return View("SignificantEventsView", model);
}
private SignificantEventsViewModel GetViewModel()
{
var viewModel = new SignificantEventsViewModel();
List<County_Codes> countyCodes = GetCountyCodeList();
List<String> stateNames = countyCodes.OrderBy(o=>o.County_st).Select(o => o.County_st ).Distinct().ToList();
viewModel.selectedState = stateNames.FirstOrDefault();
viewModel.CountyCodesList = countyCodes;
viewModel.StateNames = stateNames;
viewModel.SelectedCounties = new String[]{};
viewModel.SelectedCountyCodes = new String[] { };
viewModel.UnSelectedCounties = new String[] { };
viewModel.UnSelectedCountyCodes = new String[]{};
return viewModel;
}
The View looks like this:
#model ServicingPortal.ViewModels.SignificantEventsViewModel
#{
ViewBag.Title = "Significant Events";
}
<h2>SignificantEvents</h2>
#using (Html.BeginForm("RefreshCounties", "SignificantEvents", FormMethod.Post, new { id = "significantEventsForm", Model }))
{
<fieldset>
<span class="SpanTextboxEdit">
#Html.Label("states", "States")
<br />
<br />
#Html.DropDownListFor(o => #Model.selectedState
, new SelectList(Model.StateNames)
, new { id = "stateDropDown", onchange = "submit()", name = "test" })
</span>
</fieldset>
...
}
When the StateDropdownList is changed the veiwmodel is passed back to the controller, but the countyCodes list is always null.
I tried adding #Html.HiddenFor(o => #Model.CountyCodesList) in the view, but it still returns null. The only values that don't seem to be null are the primitive types such as String or String[]. Even the List stateNames is null.
I don't want to rebuild the county code list on each post back because there is substantial overhead involved. I have to create the list from all active loans in the database, of which there are thousands.
How can I get a List<> to persist from the view to the controller?
I should explain what I'm trying to acheive here.
I have a dropdown and a multiselect list box. The dropdown contains states and the listbox contains counties filtered by the selected state.
I need to filter the listbox contents when the selected state changes.
It would make sense to perform this task on the client side, but I have not found a good solution.
I will admit my javascript skills are quite limited.
All the solutions I researched one way or another involved filtering the county list on the server side.
I can accomplish this on the server side easy enough, but I thought that since I have already built the list, why not keep it intact instead of going to the backend each time.
The short answer is that you can't really do what you're trying to do. You're kind of trying to solve the wrong problem. You should look at using caching on the server side to prevent going back to the database to construct the county list every time.
I solved this by using TempData. On the postback action I can get the County List from temp data and set the ViewModel CountyCodeList to this value.

Sorting DataTable bound to DataGrid with custom datatypes

I have a DataTable where all column datatypes are of a custom class called CellModel.
The table's defaultview is bound to a DataGrid, which autogenerates some templatecolumns where I setup DataTemplates and Bindings, and showing the data works perfect.
My issue is when i try to sort on the columns.
I want to sort on a specific property within the custom class, but the default sorter won't recognize the custom class, so it invokes ToString() instead. By overriding and returning my property i'm able to sort, but it is PAINFULLY slow.
I've tried to implement a custom sorter on DataGrid.Sorting event like this:
private void DG_Sorting(object sender, DataGridSortingEventArgs e)
{
var column = e.Column;
e.Handled = true;
var direction = (column.SortDirection != ListSortDirection.Ascending)
? ListSortDirection.Ascending
: ListSortDirection.Descending;
var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(DG.ItemsSource);
column.SortDirection = direction;
lcv.CustomSort = new MyComparer();
lcv.Refresh();
}
But GetDefaultView returns BindingListCollectionView which don't support CustomSorters..
I'm lost. How do I implement a custom comparer for sorting the data?
Found the issue. by using the lcv.SortDescriptions and implementing the IComparer interface on the CellModel class, i was able to use custom comparison.
Also, the sorting speed was influenced since i had Virtualization disabled on the Datagrid. by enabling Virtualization, the sorting was faster.

Access Data Source Fields from Report code behind

I want to programmatically access the Fields collection in the ObjectDataSource object of my Telerik report.
I did notice in the design portion of the Telerik report you can access the fields collection
in the Value by using the Edit Expression window.
Example:
= Fields.MyFieldName
How would I accomplish this task using C# code in the report code behind file?
I had the same problem. This is how I solved it, although I believe there should be an easier way.
First I created a method for the details section itemdatabinding:
private void detail_ItemDataBinding(object sender, EventArgs e)
{
Telerik.Reporting.Processing.DetailSection section = (sender as Telerik.Reporting.Processing.DetailSection);
object id = section.DataObject["Data Field You want to access"];
Variable Name = id.ToString();
}
You can now use that variable anywhere in your codebehind.
Note: The Data Field must appear in your detail section. In my case I did not need it to show, so I just made 'Visible=false'.
This worked for me.
Bind Data to your own data to your variables
string ItemCode = "a";
string ItemDesc = "aa"
Then bind it to the data source
var Output = new
{
ItemCode = a.ItemCode,
ItemDesc = a.ItemDesc,
};
this.DataSource = Output;
All these are in code behind. Then move to design portion and modify your text-box as shown below.
= Fields.ItemCode
= Fields.ItemDesc

Linq Query Using DataTable with Paging

I have a Linq query that I copy to a DataTable which is then used to populate a gridview. I am using a group by "key" and "count" which I evaluate in the aspx page for a master/detail gridview with a repeater.
The problem that I am encountering is that the gridview datasource and bind to the datatable is not presenting me with any additional pages that are part of the data.
My query is:
// Using Linq generate the query command from the DataTable
var query = from c in dtDataTable_GridView.AsEnumerable()
group c by c.Field<string>("CLIN") into g
select new
{
Key = g.Key,
Count = g.Count(),
Items = from i in g
select new
{
CLIN = i.Field<string>("CLIN"),
SLIN = i.Field<string>("SLIN"),
ACRN = i.Field<string>("ACRN"),
CLINType = i.Field<string>("CLINType"),
Option = i.Field<string>("Option"),
Unit = i.Field<string>("Unit")
}
};
// Use extension methods to create new DataTable from query
dtTaskOrderTable = query.CopyToDataTable();
// Set the datasource
gridview1.DataSource = dtTaskOrderTable;
// Bind to the GridView
gridview1.DataBind();
If I use the original datatable (dtDataTable_GridView) directly I have paging but once I do the Linq Query and copy it back to a new datatable (dtTaskOrderTable) I lose the paging feature.
Also how do I get a value from a column name ("Option" for instance) if it is part of "Items"?
Any help would be appreciated.
Thanks,
ChrisB
Please disregard the previous answer I will delete it
It requires ICollection interface for paging.
Neither IEnumerable nore IQuerable will not work
List<(Of <(T>)>) will work as Lists implement Icollection interface
So you need
gridview1.DataSource = dtTaskOrderTable.ToList();

Resources