Фильтрация CollectionViewSource с несколькими фильтрами - PullRequest
0 голосов
/ 04 марта 2020

Я читал это: https://social.technet.microsoft.com/wiki/contents/articles/26673.wpf-collectionview-tips.aspx и безуспешно пытался применить его к моему коду.

PendingTrucks = (CollectionView)new CollectionViewSource { Source = TruckLog }.View;
ParkedTrucks = (CollectionView)new CollectionViewSource { Source = TruckLog }.View;


PendingTrucks.Filter += PendingTrucks_Filter;
ParkedTrucks.Filter += PendingTrucks_Filter;

public static ICollectionView PendingTrucks
        {
            get; set;
        }

        public static ICollectionView ParkedTrucks
        {
            get; set;
        }



static bool PendingTrucks_Filter (object value)
{
            if (value is Truck truck)
            {
                return truck.ParkItem is null;
            }

            // Fallbackvalue 
            return true;
        }

        static bool ParkedTrucks_Filter (object value)
        {
            if (value is Truck truck)
            {
                return truck.status == 2;
            }

            // Fallbackvalue 
            return true;
        }


Я получаю следующую ошибку: NullReferenceException: Object reference not set to an instance of an object..

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

Это стек вызовов, который я получаю:

This exception was originally thrown at this call stack:
    System.Windows.Data.ListCollectionView.CanAddNew.get()
    System.Windows.Controls.ItemCollection.System.ComponentModel.IEditableCollectionView.CanAddNew.get()
    System.Windows.Controls.DataGrid.OnCoerceCanUserAddOrDeleteRows(System.Windows.Controls.DataGrid, bool, bool)
    System.Windows.Controls.DataGrid.OnCoerceCanUserAddRows(System.Windows.DependencyObject, object)
    System.Windows.DependencyObject.ProcessCoerceValue(System.Windows.DependencyProperty, System.Windows.PropertyMetadata, ref System.Windows.EntryIndex, ref int, ref System.Windows.EffectiveValueEntry, ref System.Windows.EffectiveValueEntry, ref object, object, object, System.Windows.CoerceValueCallback, bool, bool, bool)
    System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, ref System.Windows.EffectiveValueEntry, bool, bool, System.Windows.OperationType)
    System.Windows.DependencyObject.CoerceValue(System.Windows.DependencyProperty)
    System.Windows.Controls.DataGrid.OnItemsSourceChanged(System.Collections.IEnumerable, System.Collections.IEnumerable)
    System.Windows.Controls.ItemsControl.OnItemsSourceChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
    System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
    ...
    [Call Stack Truncated]

1 Ответ

0 голосов
/ 05 марта 2020

Попробуйте это:

Это исходная коллекция ICollectionView. Вы добавляете / удаляете элементы из коллекции, и ICollectionView обновляется автоматически.

private ObservableCollection<Truck> Trucks { get; }

Представления вашей коллекции, которые привязываются к DataGrid:

public ICollectionView PendingTrucksCollectionView { get; }
public ICollectionView ParkedTrucksCollectionView { get; }

Инициализируйте исходную коллекцию и представления конструктора ViewModel. Здесь вы можете передать объект, который будет заполнять наблюдаемую коллекцию, или IEnumerable, чтобы заполнить коллекцию грузовиков.

public ViewModel() : this(Enumerable.Empty<Truck>())
{ }


public ViewModel(IEnumerable<Truck> trucks)
{
    // Collection Source
    Trucks = new ObservableCollection<Truck>(trucks);

    // Collection Views
    PendingTrucksCollectionView = CollectionViewSource.GetDefaultView(Trucks);
    ParkedTrucksCollectionView = CollectionViewSource.GetDefaultView(Trucks);

    // Collection View Filters
    PendingTrucksCollectionView.Filter = PendingTrucksFilter;
    ParkedTrucksCollectionView.Filter = ParkedTrucksFilter;
}

private bool PendingTrucksFilter(object value)
{
    return value is Truck truck && truck.ParkItem is null;
}

private bool ParkedTrucksFilter(object value)
{
    return value is Truck truck && truck.status == 2;
}

Надеюсь, это поможет.

...