I've a question about how to sort items in a ListView, I thought this would be really easy, but I can't seem to work it out.
The ListView is bound to an observable collection view model... the items in the list view are grouped based on certain properties by setting up a CollectionViewSource and setting up GroupDescriptions:
BrowserItemCollectionView = CollectionViewSource.GetDefaultView(_browser);
//Set up filter
BrowserItemCollectionView.Filter = FilterBrowserItems;
//Set up grouping
PropertyGroupDescription L1PGD = new PropertyGroupDescription(nameof(BrowserItem.L1group));
PropertyGroupDescription L2PGD = new PropertyGroupDescription(nameof(BrowserItem.L2group));
PropertyGroupDescription L3PGD = new PropertyGroupDescription(nameof(BrowserItem.L3group));
BrowserItemCollectionView.GroupDescriptions.Add(L1PGD);
BrowserItemCollectionView.GroupDescriptions.Add(L2PGD);
BrowserItemCollectionView.GroupDescriptions.Add(L3PGD);
I then sort the groups with:
//Setup Sorting
BrowserItemCollectionView.SortDescriptions.Add(new SortDescription(nameof(BrowserItem.L1group), ListSortDirection.Descending));
BrowserItemCollectionView.SortDescriptions.Add(new SortDescription(nameof(BrowserItem.L2group), ListSortDirection.Descending));
BrowserItemCollectionView.SortDescriptions.Add(new SortDescription(nameof(BrowserItem.L3group), ListSortDirection.Descending));
This works well and sorts the groupings in Descending order.
What I now what to do is sort the actual items - the objects that are the lowest levels of the tree views.
What method do I use to sort the actual list view items?
Thanks.
What method do I use to sort the actual list view items?
You just add another SortDescription for a property of the "lowest level" item to BrowserItemCollectionView.SortDescriptions:
BrowserItemCollectionView.SortDescriptions.Add(
new SortDescription("PropertyOfItem", ListSortDirection.Descending));
Related
I have a usercontrol, with one list box and one list view control in it. For Listview i have bound the observablecollection of type TrafficManager class as shown below:
private static ObservableCollection<TrafficManager> _trafficCollection;
public ObservableCollection<TrafficManager> TrafficCollection
{
get { return _trafficCollection; }
set
{
_trafficCollection = value;
OnPropertyChanged("TrafficCollection");
}
}
I have bound this to itemsource of list view.
Now my requirement is on selection of the listbox item, i need to filter some items of the listview. For that i used a linq to get the desired rows from list view and added that to the list view collection. Before adding i did a listview Collection TrafficCollection.Clear() and then added to that collection.But now the issue is on selection of another item in list box i need the original listview contents again to carry out the filtering using the linq again. Here once the TrafficCollection.Clear() executes the original observable collection data vanishes. How do i maintain a backup of original observable collection data "TrafficCollection" of listview. Remember i have only one view. Is there anyway to do this? Please let me know.
you can use CollectionViewSource filtering, refer here
SO Link: Trigger Filter on CollectionViewSource
this will not clear original collection.
How to sort items in ListView by column bound to an Observable Collection ?
I've looked all over the place and I can't find anything easy enough or simple on this.
Is the example here too complicated? It just shows how to use a ListCollectionView to provide the data in the correct order, and to perform the sorting.
You can use SortDescriptions in CollectionViewSource. Here is an example. If you want it dynamically, you need to code around this. but this should give you an idea.
List<Product> products = Client.GetProductList();
public ICollectionView ProductView = CollectionViewSource.GetDefaultView(products);
ProductView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
I have a ObservableCollection , where MyData is a class with 4 properties i.e. int id, string name, bool IsSelected, string IsVisible.
This ObservableCollection is binded to a combobox with checkboxes(Cities data for example). Now, when the user checks the checkboxes then next time when he opens the drop down - all selections should come on top in ascending order by name.
I have also implemented auto complete when the user types in 3 chars in the combobox, the drop down will open showing all the selections first, then then all the items starting from the 3 chars type in by the user.
I have researched and implemented the following code and it is working fine, but i want to know whether this is the best approach or can i implement this in a better manner, code is :
IEnumerable<MyData> sort;
ObservableCollection<MyData> tempSortedCities = new ObservableCollection<MyData>();
sort = City.OrderByDescending(item => item.IsSelected).ThenBy(item => item.Name.ToUpper()) ;
// City is my observablecollection<MyData> property in my Model binded to combobox in UI
foreach (var item in sort)
tempSortedCities.Add(item);
City.Clear(); // City is my observablecollection<MyData> property in my Model
City = tempSortedCities;
tempSortedCities = null;
sort = null;
Thanks in advance for your time !
ICollectionView seems to be a perfect fit for this. It was designed specifically for sorting, filtering and grouping of a collection without modifying the original collection.
You can get an instance of ICollectionView for your collection using the following code:
var sortedCities = CollectionViewSource.GetDefaultView(City);
Then you can setup sorting by adding instances of SortDescription type to the ICollectionView.SortDescriptions collection:
sortedCities.SortDescriptions.Add(new SortDescription("IsSelected", ListSortDirection.Descending));
sortedCities.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
Then you can bind your ComboBox directly to the collection view (instead of City collection) and it will display already sorted data.
Is there a way to bind an ItemsControl (like ListView or DataGrid) to a sorted collection such that:
whenever the collection is resorted via code, the ItemsControl automatically reflects the new sort order,
AND whenever the ItemsControl is sorted, it re-sorts the collection?
Thank you,
Ben
You'll need to use the
CollectionViewSource.GetDefaultView()
method to get the default view of your ObservableCollection and apply the sort on that.
For example, below I'm sorting the ObservableCollection named 'authors' by BookTitle.
ObservableCollection<Author> authors = new ObservableCollection<Author>();
authors = PopulateCollection();
// Sort by BookTitle
System.ComponentModel.ICollectionView colView;
colView = CollectionViewSource.GetDefaultView(authors);
colView.SortDescriptions.Add(new System.ComponentModel.SortDescription("BookTitle", ListSortDirection.Descending));
try to define this two attributes on the bining:
IsSynchronizedWithCurrentItem=true
BindsDirectlyToSource=true
i did not tried this but it might work..
Putting your items into an ObservableCollection and then binding to the ObservableCollection should do the trick. Any sorting done on the ObservableCollection should "translate" to the UI layer.
Ok, I have an ItemsControl binded to a List<IComparableObject>, each second the List objects change, so I have to resort them, so each second I call the List.Sort() method. Checking in the Watch panel in VS2008, I can tell the List gets sorted, but the ItemsControl doesn't. How can I make this work?
Thanks!
You have to sort the CollectionView:
List<MyObject> myInternalList = new List<MyObject>();
...
ICollectionView colView = CollectionViewSource.GetDefaultView(myInternalList);
colView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
You have to get the default view from the List.
In this case, you don't have to sort the List, because the view will always be sorted. You can add as many SortDescriptions you want.
HTH