Разбивка на страницы и фильтрация на ICollectionView WPF - PullRequest
0 голосов
/ 05 февраля 2020

У меня большой объем данных в ObservableCollection, который привязан к DataGrid через слой ICollectionView следующим образом:

public ICollectionView ProductsCollectionView
        {
            get { return CollectionViewSource.GetDefaultView(Products); }
            set { NotifyPropertyChanged("ProductsCollectionView"); refreshCollection(); }
        } 

Я хочу разрешить пользователям фильтровать эти данные с помощью строки поиска, эта часть работает а также:

ProductsCollectionView.Filter += new Predicate<object>(filterProduct);

Я также хочу добавить функцию разбиения на страницы для повышения производительности моего приложения, но я не могу понять, как объединить обе эти функции. Я попытался добавить в эту коллекцию дополнительный фильтр, который обрабатывал бы нумерацию страниц следующим образом:

ProductsCollectionView.Filter += new Predicate<object>(filterPages);

, но он дает неожиданные результаты при применении второго фильтра.

Я также пытался привязать к Вместо этого ObservableCollection и повторное инициализация его с помощью выражения LINQ каждый раз, когда происходит фильтрация, но я не могу соответственно обновить UI:

public ObservableCollection<ProductModel> Products 
{
    get 
    {
        return products;
    }
    set 
    { 
        if(products != value)
        {
            products = value;
            NotifyPropertyChanged("Products");
        }
    }
}
public ProductViewModel()
{      
        Products = db.GetProducts.Where(filterProduct).Skip(Start).Take(ItemCount).ToList();
}

Я пытался сделать то же самое на получателе ICollectionView.

У меня есть также попытался объединить оба фильтра в один и применить его к ICollectionView, это сработало, но производительность стала еще хуже:

        public bool filterProduct(object obj)
        {
            var data = obj as ProductModel;
            bool isAdded = false;
            bool toReturn = false;

            //SearchString filtering
            if (!string.IsNullOrEmpty(searchString))
            {
                isAdded = data.Name.ToString().Contains(searchString)
            }
            else
            {
                isAdded = true;
            }

            //Beginning of pagination
            if (CounterProducts == Products.Count)
            {
                CounterProducts = 0; //Counts how many products have been filtered
                CounterAdded = 0; //Counts how many products passed the string filtering
            }
            CounterProducts++;

            //Check result of searchString filtering
            if (isAdded)
            {
                CounterAdded++;
            }

            //Determine right current page
            int workingPage = 1;
            if (previousSearchString == SearchString)
            {
                workingPage = CurrentPage;
            }

            //Pagination
            if (CounterAdded > ItemsPerPage * (workingPage - 1) && CounterAdded <= (ItemsPerPage * workingPage) && isAdded)
            {
                toReturn = true;
            }

            //Last item
            if (CounterProducts == Products.Count)
            {
                previousSearchString = SearchString;
                if (CounterAdded % ItemsPerPage > 0)
                {
                    TotalPages = (CounterAdded / ItemsPerPage) + 1;
                }
                else
                {
                    TotalPages = CounterAdded / ItemsPerPage;
                }
            }

            return toReturn;
        }

Мне также нужно обновить объекты в коллекции во время выполнения , поэтому IEnumerable растворы могут не подходить здесь лучше (или я могу ошибаться?).

Я пробовал и другие способы, но я думаю, что этот вопрос уже достаточно длинный. Теперь я ищу любой совет или хороший подход для достижения как фильтрации по строке, так и нумерации страниц для сбора связанных данных. Любой вклад высоко ценится. Спасибо за ваше внимание.

1 Ответ

0 голосов
/ 07 февраля 2020

Здесь есть PagingCollectionView для Silverlight: https://github.com/microsoftarchive/SilverlightToolkit/tree/master/Release/Silverlight3/Source/System.Windows.Data/PagedCollectionView

Действие по сборке для файла ресурса PagedCollectionViewResources.resx должно быть Встроенным ресурсом.

Вы Также следует исправить имя ресурса в классе PagedCollectionViewResources (оно находится в файле PagedCollectionViewResources.Designer.cs). Он должен иметь полное пространство имен файла ресурсов.

Например, у меня есть dll с именем Library.Wpf. Материал подкачки находится в каталоге Paging, а файл ресурсов находится в этом каталоге.

> Library.Wpf
  … other stuff
  > Paging
    … other files 
     > PagedCollectionViewResources.resx
       > PagedCollectionViewResources.Designer.cs

, а мое свойство ResourceManager выглядит следующим образом:

internal static global::System.Resources.ResourceManager ResourceManager {
    get {
        if (object.ReferenceEquals(resourceMan, null)) {
            global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Library.Wpf.Paging.PagedCollectionViewResources", typeof(PagedCollectionViewResources).Assembly);
            resourceMan = temp;
            }
        return resourceMan;
        }
    }

Я не могу проверить работает ли он, но компилируется без ошибок.

...