Sort and filter not working .net maui

tim 200 Reputation points
2024-10-10T13:37:02.0266667+00:00

I'm trying to add a filter and sort to my app.

the sort and filter func code are stepped thru but does not work, I do not see any data in the checkListItem

I think the issue is the use of SourceCache ( I found sort/filer sample code and tried to add parts to my code , the sample uses hard coded items, but I need to load from json file)

( I have the Sample code also in the app as a test, and it works )

CheckListPageSortModel.cs


using MapleSugar.Models;
using MapleSugar.Services;
using MapleSugar.ViewModels.Buttons;

namespace MapleSugar.PageModels
{
    public class CheckListPageSortModel : ReactiveObject, IDisposable
    {
        public CheckListPageSortModel()
        {      

        //Search logic
        Func<CheckListItem, bool> treeFilter(string text) => checklistItem =>
            {
                return string.IsNullOrEmpty(text) || checklistItem.TreeLocation.ToLower().Contains(text.ToLower()) || checklistItem.TreeNumber.ToString().Contains(text.ToLower());
            };

            var filterPredicate = this.WhenAnyValue(x => x.SearchText)
                                      .Throttle(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
                                      .DistinctUntilChanged()
                                      .Select(treeFilter);

            //Filter logic
            Func<CheckListItem, bool> sectorFilter(string sector) => checklistItem =>
            {
                return sector == "All" || sector == checklistItem.Sector.ToString();
            };

            var sectorPredicate = this.WhenAnyValue(x => x.SelectedSectorFilter)
                                       .Select(sectorFilter);

            //sort
            var sortPredicate = this.WhenAnyValue(x => x.SortBy)
                                    .Select(x => x == "SortField" ? SortExpressionComparer<CheckListItem>.Ascending(a => a.Sector) : SortExpressionComparer<CheckListItem>.Ascending(a => a.TreeNumber));

            _cleanUp = _sourceCache.Connect()
            .RefCount()
            .Filter(sectorPredicate)
            .Filter(filterPredicate)
            .Sort(sortPredicate)
            .Bind(out _myItems)
            .DisposeMany()
            .Subscribe();

            //Set default values
            SelectedSectorFilter = "All";
            SortBy = "SortField";

          //  AddCommand = ReactiveCommand.CreateFromTask(async () => await ExecuteAdd());
          // DeleteCommand = ReactiveCommand.Create<CheckListItem>(ExecuteRemove);
           SortCommand = ReactiveCommand.CreateFromTask(ExecuteSort);
         //   WorkTreeLocationItems = new ObservableCollection<WorkTreeLocationItem>();
           Load_Button_Clicked = new ButtonModel("Load Data", LoadCheckListAction);
           // OnEditCommand = new Command(OnEditCommandAction);
        }
      
            
        ButtonModel _load_Button_Clicked;
        public ButtonModel Load_Button_Clicked
        {
            get;
            set;
        }       
        
        private async Task ExecuteSort()
        {
            var sort = await App.Current.MainPage.DisplayActionSheet("Sort by", "Cancel", null, buttons: new string[] { "Name", "Type" });
            if (sort != "Cancel")
            {
                SortBy = sort;
            }
        }

        public void Dispose()
        {
            _cleanUp.Dispose();
        }

        public ReadOnlyObservableCollection<CheckListItem> CheckListItems => _myItems;

        public string SearchText
        {
            get => _searchText;
            set => this.RaiseAndSetIfChanged(ref _searchText, value);
        }

        public string SelectedSectorFilter
        {
            get => _selectedSectorFilter;
            set => this.RaiseAndSetIfChanged(ref _selectedSectorFilter, value);
        }

        private string SortBy
        {
            get => _sortBy;
            set => this.RaiseAndSetIfChanged(ref _sortBy, value);
        }

        private async void LoadCheckListAction()
        {
            try
            {
                var file = await FilePicker.PickAsync();

                if (file != null)
                {

                    var items = from Trees in CheckListService.GetSTrees(File.ReadAllText(file.FullPath))
                                orderby Trees.Sector, Trees.TreeNumber, Trees.SubTreeNumber, Trees.TreeSubLetter
                                group Trees by Trees.Sector.ToString().ToUpperInvariant() into sectorGroup
                                select new Grouping<string, CheckListItem>(sectorGroup.Key, sectorGroup);

                    foreach (var g in items)
                        _myItems.Add(g);

                }
            }
            catch (Exception)
            {

            }
        }        

        public ReactiveCommand<Unit, Unit> AddCommand { get; set; }
        public ReactiveCommand<CheckListItem, Unit> DeleteCommand { get; }
        public ReactiveCommand<Unit, Unit> SortCommand { get; }

        private SourceCache<CheckListItem, string> _sourceCache = new SourceCache<CheckListItem, string>(x => x.Sector.ToString());
        private readonly ReadOnlyObservableCollection<CheckListItem> _myItems;
        private string _searchText;
        private string _selectedSectorFilter;
        private string _sortBy;

        private readonly IDisposable _cleanUp;
    }
}

TIA

Tim

here is part of the sample code I got the code from and why I think the sourceCache is the issue

MainViewModel.cs

using MapleSugar.Models;

namespace MapleSugar.PageModels
{
    public class MainViewModel : ReactiveObject, IDisposable
    {
        public MainViewModel()
        {
            // Initial data
            _sourceCache.AddOrUpdate(new List<Restaurant>()
            {
                new Restaurant("Yao","Casual","Asian Fusion","Dominican Republic"),
                new Restaurant("Chef Pepper","Casual","International","Dominican Republic"),
                new Restaurant("Bottega Fratelli","Formal","International","Dominican Republic"),
                new Restaurant("McDonalds","Fast Food","Burgers","United States"),
                new Restaurant("Burger King","Fast Food","Burgers","United States"),
                new Restaurant("Sushi Nation","Casual","Sushi","Venezuela"),
                new Restaurant("Pollo Victorina","Fast Food","Chicken","Dominican Republic"),
                new Restaurant("Pollo Rey","Fast Food","Chicken","Dominican Republic"),
                new Restaurant("Asadero Argetino","Formal","Meat","Dominican Republic"),
                new Restaurant("Hooters","Casual","Wings","United States"),
                new Restaurant("Andres Carne","Casual","Meat","Colombia"),
                new Restaurant("La Casita","Casual","Colombian Food","Colombia"),
                new Restaurant("Cielo","Formal","International","Colombia"),
            });

            //Search logic
            Func<Restaurant, bool> restaurantFilter(string text) => restaurant =>
            {
                return string.IsNullOrEmpty(text) || restaurant.Name.ToLower().Contains(text.ToLower()) || restaurant.Type.ToLower().Contains(text.ToLower());
            };

     var filterPredicate = this.WhenAnyValue(x => x.SearchText)
                               .Throttle(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
                               .DistinctUntilChanged()
                               .Select(restaurantFilter);
     //Filter logic
     Func<Restaurant, bool> countryFilter(string country) => restaurant =>
     {
         return country == "All" || country == restaurant.Country;
     };
     var countryPredicate = this.WhenAnyValue(x => x.SelectedCountryFilter)
                                .Select(countryFilter);
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,580 questions
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 76,391 Reputation points Microsoft Vendor
    2024-10-14T08:27:53.96+00:00

    Hello,

    all my code works, but I don't 100% understand what the sort/filter code is doing, but I think i don't need the following

    Yes, You have created public ObservableCollection<Grouping<string, CheckListItem>> MyItems { get; set; } = new ObservableCollection<Grouping<string, CheckListItem>>();, do not need ReadOnlyObservableCollection and SourceCache.

    can't figure out how to point the sort/filter code to groupded collection.

    If you have a class like following CheckListItem

    public class CheckListItem
    {
        public string Name { get; set; }
        public string Category { get; set; } // This will be used as a grouping key
        // Other properties can be added
    }
    
    

    And Grouping class like following code.

    public class Grouping<TKey, TElement> : ObservableCollection<TElement>
    {
        public TKey Key { get; private set; }
    
        public Grouping(TKey key, IEnumerable<TElement> items)
        {
            Key = key;
            foreach (var item in items)
            {
                this.Items.Add(item);
            }
        }
    }
    

    You can now use LINQ to group and sort your collection of CheckListItem objects.

    var items = new ObservableCollection<CheckListItem>
            {
                new CheckListItem { Name = "Item1", Category = "Group1" },
                new CheckListItem { Name = "Item2", Category = "Group2" },
                new CheckListItem { Name = "Item3", Category = "Group1" },
                new CheckListItem { Name = "Item4", Category = "Group3" }
            };
    
            // Group and sort items by category
            var groupedItems = items
                .GroupBy(item => item.Category)                 // Group by category
                .Select(group => new Grouping<string, CheckListItem>(group.Key, group.OrderBy(item => item.Name)))  // Sort each group by Name
                .OrderBy(g => g.Key);                           // Optionally, sort the groups by key
    
            MyItems = new ObservableCollection<Grouping<string, CheckListItem>>(groupedItems);
    

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.