how to sort descending order of ObservableCollection into WP7.? - sorting

I want to sort my ObservableCollection into the Descending Order I had tried with different scenario but I am not able to sort it my code is like this.
1>
LeaderboardItems = new ObservableCollection<AEGAPI.clsAEGAPI.Leaderboard>(LeaderboardItems.OrderByDescending(a => a.Points));
2>
LeaderboardItems.OrderByDescending(p => p.Points);
I had tried lots of but I am not able to get my result.

Normally you can't sort a ObservableCollection, because than you are changing the collection. If you only want to show the sorted list:
List<AEGAPI.clsAEGAPI.Leaderboard> list = LeaderboardItems.OrderByDescending(p => p.Points).ToList()
Or you can directly bind the source to a listbox
listbox.ItemsSource = LeaderboardItems.OrderByDescending(p => p.Points)
The list will not react to changes on the observable collection. You have to implement it your self.
In the past i found someone who has made a sortable observable collection, maybe you can go for that option (search for : sortableobservablecollection), but is was a bit complex.
Greets

Related

Adding a custom sorting to listing with an aggregate in shopware 6

I am trying to build a custom sorting for the product listings in shopware 6.
I want to include a foreign table (entity is: leasingPlanEntity), get the min of one of the fields of that table (period_price) and then order the search result by that value.
I have already built a Subscriber, and try it like that, what seems to work.
public static function getSubscribedEvents(): array
{
return [
//ProductListingCollectFilterEvent::class => 'addFilter'
ProductListingCriteriaEvent::class => ['addCriteria', 5000]
];
}
public function addCriteria(ProductListingCriteriaEvent $event): void
{
$criteria = $event->getCriteria();
$criteria->addAssociation('leasingPlan');
$criteria->addAggregation(new MinAggregation('min_period_price', 'leasingPlan.periodPrice'));
// Sortierung hinzufügen.
$availableSortings = $event->getCriteria()->getExtension('sortings') ?? new ProductSortingCollection();
$myCustomSorting = new ProductSortingEntity();
$myCustomSorting->setId(Uuid::randomHex());
$myCustomSorting->setActive(true);
$myCustomSorting->setTranslated(['label' => 'My Custom Sorting at runtime']);
$myCustomSorting->setKey('my-custom-runtime-sort');
$myCustomSorting->setPriority(5);
$myCustomSorting->setFields([
[
'field' => 'leasingPlan.periodPrice',
'order' => 'asc',
'priority' => 1,
'naturalSorting' => 0,
],
]);
$availableSortings->add($myCustomSorting);
$event->getCriteria()->addExtension('sortings', $availableSortings);
}
Is this already the right way to get the min(periodPrice)? Or is it taking just a random value out of the leasingPlan table to define the sort-order?
I didn't find a way, to define the min_period_price aggregate value in the $myCustomSorting->setFields Methods.
Update 1
Some days later, I asked a less complex question in the shopware community on slack:
Is it possible to use the DAL to define a subquery for an association in the product-listing?
It should generate something like:
FROM
JOIN (
SELECT ... FROM ... WHERE ... GROUP BY ... ORDER BY ...
) AS ...
The answer there was:
Don't think so
Update 2
I also did an in-deep anlysis of the DAL-Query-Builder, and it really seems to be not possible, to perform a subquery with the current version.
Update 3 - Different approach
A different approach might be, to define custom fields in the main entity. Every time a change is made on the main entity, the values of this custom fields should be recalculated.
It is a lot of overhead work, to realize this. Especially when the fields you are adding, are dependend on other data like the availability of a product in the store, for example.
So check, if it is worth the extra work. Would be better, to have a solution for building subqueries.
Unfortunately it seems that in your case there is no easy way to achieve this, if I understand the issue correctly.
Consider the following: for each product you can have multiple leasingPlan entities, and I assume that for a given context (like a specific sales channel or listing) that still holds. This means that you would have to sort the leasingPlan entities by price, then take the one with the lowest price, and then sort the products by their lowest-price leasingPlan's price.
There seems to be no other way to achieve that, and unfortunately for you, sorting is applied at the end, even if it is sort of a subquery.
So, for example, if you have the following snippet
$criteria = $event->getCriteria();
$criteria->addAssociation('leasingPlan');
$criteria->getAssociation('leasingPlan')
->addSorting(new FieldSorting('price', FieldSorting::ASCENDING))
->setLimit(1)
;
The actual price-sorting would be applied AFTER the leasingPlan entities are fetched - essentially the results would be sorted, meaning that you would not get the cheapest leasing plan per product, instead getting the first one.
You can only do something like that with filters, but in this case there is nothing to filter by - I assume you don't have one leasingPlan per SalesChannel or per language, so that you could limit that list to just one entry that could be used for sorting
That is not to mention that this could not be included in a ProductSortingEntity, but you could always work around that by plugging into the appropriate events and modifying the criteria during runtime
I see two ways to resolve your issue
Making another table which would store the cheapest leasingPlan per product and just using that as your association
Storing the information about the cheapest leasingPlans in e.g. cache and using that for filtering (caution: a mistake here would probably break the sorting, for example if you end up with too few or too many leasingPlans per product)
public function applyCustomSorting(ProductListingCriteriaEvent $event): void
{
// One leasingPlan per one product
$cheapestLeasingPlans = $this->myCustomService->getCheapestLeasingPlanIds();
$criteria = $event->getCriteria();
$criteria->addAssociation('leasingPlan');
$criteria->getAssociation('leasingPlan')
->addSorting(new FieldSorting('price', FieldSorting::ASCENDING))
->addFilter(new EqualsAnyFilter('id', $cheapestLeasingPlans))
;
}
And then you could sort by
$criteria->addSorting(new FieldSorting('leasingPlan.periodPrice', FieldSorting::ASCENDING));
There should be no need to add the association manually and to add the aggregation to the criteria, that should happen automatically behind the scenes if your custom sorting is selected in the storefront.
For more information refer to the official docs.

.net core when I read from appsettings, the sort is changed. Why?

I have this config in appsettings.json:
"CategoriesTypes": [ "Country", "State", "Semester" ],
in the code I read values like:
var array = Configuration.GetSection("CategoriesTypes").AsEnumerable() .Where(o => !string.IsNullOrEmpty(o.Value)).Select(o => o.Value).ToArray()
// output of foreach loop:
"Semester", "State", "Country"
Why The sort is changed?
IEnumerable do not pretend to keep items in order, unless you ask for. And as described in the docs
Methods that are used in a query that returns a sequence of values do not consume the target data until the query object is enumerated.
When you iterate through an IEnumerable it is just navigating to the previous/next item without knowing it in advance. So IEnumerable do not keep items sorted, because sorting requires to enumerate through the whole items in the list.
If you need to sort the list just use Linq extensions OrderBy or OrdrByDescending which will return IOrderedEnumerable<T>.

Realm React native sorted order

Basically I have a MessageSchema with a date property, on my app I need to query all the messages stored on the database and be able to sort them by their date to display them on a ListView, I do the query as follows:
return realm.objects("Message").sorted('date');
This works, but only one way, the messages are sorted on ascending order only, I haven't found a way to do it on descending order and the docs of the react native only show one example:
let hondas = realm.objects('Car').filtered('make = "Honda"');
// Sort Hondas by mileage
let sortedHondas = hondas.sorted('miles');
Any advice is welcome.
Versions:
react-native: "0.40.0"
realm js: "1.0.2"
return realm.objects("Message").sorted('date', true);
Looking at the source code you can see that the sorted method expects
a descriptor and a Boolean named reverse, that it is set as false unless
you change it, so the code above just reverses the order.

Is there a way to merge multiple properties and then sort via LINQ?

I'm working on a class that has URL and FileName fields. An object can either have a URL or a FileName, but can't have both at the same time.
Is there any way to merge these two fields via LINQ and then sort them? I know I can't use
OrderBy(i => item.URL).ThenBy(i => item.FileName);
because it would just sort the items via URL first and then by their respective FileNames. I need to sort it as if I'm sorting only one field.
Thank you :)
var sorted = list.OrderBy(x => x.URL + x.FileName);
You can pad the URL if desired, or do just about any other operation you need.

Sorting an observable collection with linq

I have an observable collection and I sort it using linq. Everything is great, but the problem I have is how do I sort the actual observable collection? Instead I just end up with some IEnumerable thing and I end up clearing the collection and adding the stuff back in. This can't be good for performance. Does anyone know of a better way to do this?
If you are using Silverlight 3.0, then using CollectionViewSource is the cleanest way. Refer below example: (it can be done via xaml as well)
ObservableCollection<DateTime> ecAll = new ObservableCollection<DateTime>();
CollectionViewSource sortedcvs = new CollectionViewSource();
sortedcvs.SortDescriptions.Add(new System.ComponentModel.SortDescription("Date",
System.ComponentModel.ListSortDirection.Ascending));
sortedcvs.Source = ecAll;
ListBoxContainer.DataContext = sortedcvs;
And in corresponding xaml set
ItemsSource="{Binding}"
for the ListBox or any ItemsControl derived control
Since the collection doesn't provide any Sort mechanism, this is probably the most practical option. You could implement a sort manually using Move etc, but it will probably be slower than doing in this way.
var arr = list.OrderBy(x => x.SomeProp).ToArray();
list.Clear();
foreach (var item in arr) {
list.Add(item);
}
Additionally, you might consider unbinding any UI elements while sorting (via either approach) you only pay to re-bind once:
Interestingly, if this was BindingList<T>, you could use RaiseListChangedEvents to minimise the number of notifications:
var arr = list.OrderBy(x => x).ToArray();
bool oldRaise = list.RaiseListChangedEvents;
list.RaiseListChangedEvents = false;
try {
list.Clear();
foreach (var item in arr) {
list.Add(item);
}
} finally {
list.RaiseListChangedEvents = oldRaise;
if (oldRaise) list.ResetBindings();
}
Note that in Linq, you are given an IEnumerable from your query, and that query has not executed yet. Therefore, the following code only runs the query once, to add it to an ObservableCollection:
var query = from x in Data
where x.Tag == "Something"
select x;
foreach(var item in query)
MyObservableCollection.Add(item);
Take a look at the "OrderBy" extension on IEnumerable:
foreach(var item in query.OrderBy(x => x.Name))
MyObservableCollection.Add(item);
ObservableCollections aren't designed to be sortable. List is sortable, and that's the underlying mechanism used by the answer referencing List.Sort(), but ObservableCollection isn't derived from List so you're out of luck there. Imo, the "right" solution is not to try to sort the ObservableCollection, but to implement ICollectionView and bind an instance of that to your control. That interface adds methods for sorting and has the additional benefit that its recognized by Silverlight controls (well, the ones that support it anyway such as DataGrid) so your sorting could be utilized directly from the UI layer. This question might be helpful:
Silverlight and icollectionview
i followed the link mentioned in this post http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75
but having issues getting it to work in Silverlight
I created a property public SortableObservableCollection Terms
When I call Terms.Sort(new TermComparer()) the records are still display unsorted on the UI
could some suggest what could be going wrong. thanks
I found this on CodePlex:
Sorted Collections
Haven't used it yet though.
Rick

Resources