This is a migrated thread and some comments may be shown as answers.

RadListView group, sort, filter descriptors

9 Answers 350 Views
ListView
This is a migrated thread and some comments may be shown as answers.
Jonathan
Top achievements
Rank 1
Jonathan asked on 21 Jan 2017, 11:37 AM

Hi,

 

I'm having a hard time wrapping my head around how to handle list view group, sort and filter descriptors in an MVVM fashion.

My scenario is pretty simple: change the grouping, sorting or filtering rules of a list view by clicking a button.

Like so: Button => click => issue View Model command => affect change to the grouping, sorting, filtering rules owned by the view model that are supposedly bound to the list view

 

But here are some problems:

- The descriptors cannot be bound.

- The descriptors are read-only properties of type ObservableCollection, which means that they are owned by the RadListView instance. The caller cannot set an ObservableCollection owned by the view model.

So here are a couple of ideas I have been playing around with, both pretty bad:

- So one can write descriptors with bound properties to the view model (e.g. the sorting order), and force the list view to reload from the view model (by setting the ItemsSource to a new collection instance of the same items via a binding, which is ugly and causes flickering if the item count is high but couldn't find any other way).

- Or, I'll say presumably because I haven't tested that assumption, modify the descriptors' ObservableCollection on the list view (e.g. remove an alphabetical ascending sort descriptor from the collection and add a descending sort descriptor). This means having a reference to the list around when such change is needed. To avoid coupling the view and the view model, this could happen in the parent view, or page, and be isolated from the view model. Which is not great for reusing those features in different views with the same view model...

 

Does anyone have real life experience on that matter and could enlighten us on how to approach this?

 

And question for the Telerik staff: Why aren't the descriptor properties bindable and/or settable? Are they planned to be bindable and/or settable at some point?

 

Thanks in advance,

Jonathan

9 Answers, 1 is accepted

Sort by
0
Jonathan
Top achievements
Rank 1
answered on 21 Jan 2017, 12:58 PM

Some interesting findings on a ~400 items list while changing the grouping (or sorting):

- NOT changing the ItemsSource BUT changing the descriptors (clear the descriptors collection then add a new descriptor) = huge lag

- NOT changing the descriptors (using delegates to pick the right property to group or sort by) BUT changing the ItemsSource (just to trigger the descriptors to be re-evaluated, it's a new instance but the items are the same) = totally smooth

0
Tsvyatko
Telerik team
answered on 25 Jan 2017, 03:29 PM
Hi Jonathan,

Thank you for contacting us!

Indeed, currently Listview descriptors are not bindable properties which makes them hard to be consumed directly in the viewmodel. Currently, it can be achieved by using attached behavior by passing its instance from the listview into the viewmodel.

We do have plans to make these properties bindable for easier usage from viewmodel directly. I have logged this as a public feedback item, so you can track its progress - https://feedback.telerik.com/Project/168/Feedback/Details/211065-listview-make-descriptors-collection-bindable-properties.

Regarding the performance issue reported - would it be possible to share come additional information regarding the setup as well as the platform on which you encounter this problem.

Regards,
Tsvyatko
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jonathan
Top achievements
Rank 1
answered on 30 Jan 2017, 04:55 PM

Hi Tsvyatko,

 

Thanks for opening a public feedback item!

 

The performance issue is most apparent on Android. I benchmarked the number of calls made to the sorting and grouping descriptors' extractor and comparer methods on Android and iPhone with the same collection containing 428 objects.

This is the result when changing the grouping descriptors; actually, an instance of the same delegate descriptor is inserted in the collection:

- iOS:

    - sort comparer: 3249

    - group extractor: 427

- Android (a Moto X will hang for about 10 seconds with a debug build):

    - sort comparer: 12707
    - group extractor: 1015

So ~4x the hit the amount of work!

Removing the grouping on the Android build reduces the hit by half.

Also, I noticed that:

- making the sort comparer only return 0 has little to no effect on the performance hit.

- clearing the descriptors' collection before adding a new one ends up in twice the amount of operations or so.

- modifying any of the descriptor collections makes all the descriptors to be re-evaluated (the old descriptor about to be removed is also evaluated)

 

Is there a preferred way to deal with descriptor? Is there a tutorial or an example showing best practices?

Let me know if I can help in anyway, this is really a show stopper.

 

Best regards,

Jonathan

0
Jonathan
Top achievements
Rank 1
answered on 31 Jan 2017, 10:09 AM

Hi,

 

I've set up a minimal test project that can be downloaded here (for the next 15 days): https://we.tl/JcFRUfNFpF

It highlights the issues I've been describing.

 

Best regards,

Jonathan

0
Jonathan
Top achievements
Rank 1
answered on 01 Feb 2017, 12:19 PM

Hi,

 

Further testing seems to indicate that the fastest way to refresh the list view (forcing it to re-evaluate the descriptors) is to assign the bound items source to a new instance, which would end up in something like this:

Items = new ObservableCollection<Item>(Items);

 

Using MVVM Light, I would have expected raising a property changed event to do the trick:

RaisePropertyChanged(nameof(ViewModel.Items));

The event is received when listening to changes, but the list view is not refreshed...

 

I've updated the previous sample project with MVVM Light and Realm (download will work for the next 15 days): https://we.tl/RQ7Mk3YWtV

 

Best regards,

Jonathan

0
Petar Marchev
Telerik team
answered on 02 Feb 2017, 01:30 PM
Hello Jonathan,

Thank you for the attached project. I was able to test your project, and create my own project too, only to confirm that this scenario is suspiciously slow in Android. I do not think that the hit count itself is a problem, because using the sorting from System.Linq gives me a higher hit count. However System.Linq sorting is super fast for this, and a larger, data set, which suggests that the performance in Android can be improved. I will log this so that we can investigate in detail.

I created a feedback item which you can vote for and track its status. I have updated your Telerik points as a thank you for letting us know of this issue and helping us improve our product.

At the moment we cannot suggest a better approach. Let us know if you have other questions.

Regards,
Petar Marchev
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jonathan
Top achievements
Rank 1
answered on 02 Feb 2017, 02:52 PM

Hi Petar,

 

Thanks for creating a feedback item for the performance issue.

 

Back to my previous question:

[quote]Further testing seems to indicate that the fastest way to refresh the list view (forcing it to re-evaluate the descriptors) is to assign the bound items source to a new instance, which would end up in something like this:
Items = new ObservableCollection<Item>(Items);

Using MVVM Light, I would have expected raising a property changed event to do the trick:
RaisePropertyChanged(nameof(ViewModel.Items));
The event is received when listening to changes, but the list view is not refreshed...[/quote]

 

Best regards,

Jonathan

0
Petar Marchev
Telerik team
answered on 03 Feb 2017, 08:55 AM
Hi Jonathan,

I don't see a problem with the scenario you propose. When invoking the PropertyChanged notification, you are essentially saying that this property changed and anybody interested in this change should update accordingly. However, in reality your property value did not change, and the framework detects this, and since there has been no change - the PropertyChanged chain is not  triggered.

Consider this custom view:
public class CustomView : View
{
 public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
  nameof(ItemsSource),
  typeof(IEnumerable),
  typeof(CustomView),
  null,
  BindingMode.OneWay,
  null,
  OnItemsSourcePropertyChanged);
 
 public IEnumerable ItemsSource
 {
  get
  {
   return (IEnumerable)this.GetValue(ItemsSourceProperty);
  }
  set
  {
   this.SetValue(ItemsSourceProperty, value);
  }
 }
  
 private static void OnItemsSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
 {
 }
}

You can now use it the same way you are using the listview:
var customView = new CustomView
{
 BindingContext = vm,
};
 
listView.SetBinding(RadListView.ItemsSourceProperty, new Binding(nameof(ViewModel.Source)));
customView.SetBinding(CustomView.ItemsSourceProperty, new Binding(nameof(ViewModel.Source)));

Place a break point in the OnItemsSourceChanged handler and see that the handler is not invoked upon raising the property changed notification.

Even if the handler was invoked, this does not guarantee an update, because often we use a specific object to handle the items, something like a CustomItemsSourceProxy. And in the previously mentioned OnItemsSourcePropertyChanged handler, the code looks like this:
private static void OnItemsSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
 RadVisual v = (RadVisual)bindable;
 v.itemsSourceProxy.ItemsSource = newValue;
}

So again here the proxy will not detect a change in its ItemsSource and no action will be triggered. I hope this explanation helps.

Regards,
Petar Marchev
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jonathan
Top achievements
Rank 1
answered on 03 Feb 2017, 09:13 AM

Hi Petar,

 

Thank you very much for the clarification.

 

Best regards,

Jonathan

Tags
ListView
Asked by
Jonathan
Top achievements
Rank 1
Answers by
Jonathan
Top achievements
Rank 1
Tsvyatko
Telerik team
Petar Marchev
Telerik team
Share this question
or