Selection Persistance on Filtering

2 posts, 0 answers
  1. Andrew
    Andrew avatar
    7 posts
    Member since:
    Dec 2012

    Posted 13 Jun 2018 Link to this post

    Hi,

    I'm using XamarinForms and have a telerik listview and an entry on a page and am using the entry to filter the listview. I have the filter wired up to my ViewModel and it is working without issue. However, I now notice that the multiple section that is enabled does not persist after the filter is applied. And since the SelectedItems property cannot be bound in MVVM, I cannot easily re-apply those selected items. Is there a property/workaround that will allow that persistence?

  2. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1168 posts

    Posted 15 Jun 2018 Link to this post

    Hi Andrew,

    I'm not sure if you work with Marcus, but I just answered a similar question from him. In case he isn't your colleague, let me share my demo, and what I wrote, with you because it's the same answer (in between the horizontal rules below).

    Before I share that, I wanted to briefy touch on your comment about the RadListView.SelectedItems collection not being MVVM binding settable. While it is true you can't set the property using a binding, you can use a OneWayToSource binding mode so that a view model property acts as a reference (also works for the FilterDescriptors, SortDescriptors and GroupDescriptors collections).

    Here's a small example:

    view

    <dataControls:RadListView GroupDescriptors="{Binding MyGroupDescriptors, Mode=OneWayToSource}" ... />

    view model

    public class CustomersViewModel : BaseViewModel
    {
        public CustomersViewModel()
        { }
         
        public ObservableCollection<GroupDescriptorBase> MyGroupDescriptors { getset; }
     
        private void GroupItems(string propertyToGroupBy)
        {
            GroupDescriptors.Clear();
                 
            if (string.IsNullOrEmpty(propertyToGroupBy))
                return;
     
            switch (propertyToGroupBy)
            {
                case "None":
                case null:
                    GroupDescriptors.Clear();
                    break;
                default:
                    GroupDescriptors.Add(new PropertyGroupDescriptor { PropertyName = propertyToGroupBy });
                    break;
            }
        }
    }



    Okay, now onto my answer about the selected items...





    The issue with losing the selection is that the filtering is most likely removing the item from the bound ItemsSource. Therefore the RadListView no longer has a reference to the item that was removed, thus the selection is lost.  Ultimately, the selected item needs to be in the items source. 

    Solution

    To fix this, don't filter out the bound items source. Instead, use the use the built-in RadListView Filtering. This was built for speed and efficiency and maintains all the states of the items (including selection state).

    I've attached an example that demonstrates this approach, run the demo and do the following:

    1 - Select the first 2 or 3 items 
    2 - Click the button to filter out items that are not between 25 and 35 years old (notice the selected items were filtered out)
    3 - Click the button again to remove the filter (notice the items are still selected)

    You can filter the RadListView by simply adding and removing FilterDescriptors form the RadListView's FilterDescriptors collection.

    In my demo, I use the following:

    private void Button_OnClicked(object sender, EventArgs e)
    {
        if (isFiltered)
        {
            // Clears filters
            radListView1.FilterDescriptors.Clear();
        }
        else
        {
            // create the filter
            var filter = new DelegateFilterDescriptor {Filter = AgeFilter};
      
            // adding it to the RadListView will immediately filter the UI
            radListView1.FilterDescriptors.Add(filter);
        }
      
        isFiltered = !isFiltered;
    }
      
    private bool AgeFilter(object arg)
    {
        var age = ((DataItem)arg).Age;
        return age >= 25 && age <= 35;
    }

    Note: You also do the same with Grouping and Sorting. Both of these are also fast and efficient.


    Custom Approaches

    You could go outside the functionality of the RadListView and build a custom approach to persist the selection value. 

    1 - Persist selection state in the data model

    You could have a property on  the data model that demotes it needs to be selected after being added back in to the RadListView. Then when an item is added/removed to the RadListView's ItemsSource (probably using the CollectionChanged event handler), you can add or remove that item from the RadListView's SelectedItems collection.

    2 - Keep a separate backing collection for SelectedItems

    You could persist the selected items in a separate collection. When you select/deselect an item you can add/remove it from the backing selected items collection. Then, whenever filtering is complete, you iterate over the selected items, find a match in the ItemsSource and add it to the ListView.SelectedItems collection to make the selection. This is similar to what we dointernally.

    This requires 3 collections:

    - Original Items (this contains all 2000 items)
    - FilteredItems (this is bound to the RadListView and is populated by the results of the filtering of OriginalItems)
    - BackingSelectedItems (this is where items are add/removed when the RadListView's SelectionChanged event fires)

    I do not recommend this approach, it is prone to edge cases and bugs.

    We don't have any examples of the approaches above because it's not a RadListView API, rather they general C# programming concepts that apply to any items control that has a SelectedItems property.




    Wrapping Up

    If this answers your question, you can use the "Mark as resolved" button. If you have any further trouble, let me know (share any relevant code so I can investigate directly).

    Thank you for contacting Support and for choosing UI for Xamarin.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    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
Back to Top