none
WPF. Как обновлять программно данные в DataGrid, чтобы каждый раз фильтровать строки коллекции и показывать только нужные? RRS feed

  • Вопрос

  • Имеется DataGrid (проект WPF), имеется контрол (ListBox). Данные списка (ListBox) могут быть данными конкретной колонки в DataGrid. Мне бы хотелось, активизируя элемент списка динамически фильтровать строки в таблице данных.

    Я решил использовать CollectionViewSource и его событие Filter (CollectionViewSource.Filter Event), об этом прочитал еще в Filter a DataGrid in WPF. Строки отбираются, но только один раз, не могу понять, что мне сделать, чтобы обновить данные и при этом вызвать функцию фильтра?

                CollectionViewSource cvs = new CollectionViewSource() { Source = GetTestObject()};
                cvs.Filter += new FilterEventHandler(MyFilter);
                ICollectionView listView = cvs.View;

                dgData.ItemsSource = listView;

    GetTestObject() - просто возвращает List<MyObject>, а MyFilter - удовлетворяет требованиям FilterEventHandler и изменяет e.Accepted в зависимости от того, соответствует значение в строке текущему элементу (SelectedItem) в ListBox или нет.

    Обновлять содержимое таблицы я планирую в обработчике _SelectionChanged списка ListBox. Фильтрация происходит однажды - при инициализации ItemsSource, как мне ее вызывать по необходимости?


Ответы

  • Добрый день.

    Свойству Filter вашего экземпляра CollectionViewSource присвойте null, а потом опять метод фильтрации. И данные обновятся и фильтр присвоится.

    • Помечено в качестве ответа Denis Prokofjev 4 мая 2017 г. 7:55
    Отвечающий

Все ответы

  • Попробовал сделать вот так:

                // нужно выполнить отбор строк по данному значению.
                if ((dgData.ItemsSource as ICollectionView) != null)
                    (dgData.ItemsSource as ICollectionView).Refresh();

    Но не впечатлило... создается впечатление, что фильтр отключается - я больше не попадаю в обработчик фильтра и всегда вижу все строки. Этот подход не сработал.

  • Добрый день.

    Свойству Filter вашего экземпляра CollectionViewSource присвойте null, а потом опять метод фильтрации. И данные обновятся и фильтр присвоится.

    • Помечено в качестве ответа Denis Prokofjev 4 мая 2017 г. 7:55
    Отвечающий
  • Добрый день! Алексей, спасибо, получилось!

    if (CollViewSource != null)
                {
                    //CollViewSource.Filter += null;
                    CollViewSource.Filter += new FilterEventHandler(MyFilter);
                }

    Только я не очень понял, как обнулить свойство Filter? Использовать простой знак "=" компилятор не дает, можно только "+=". В данном контексте "=" и "+=" одинаковые операции? Где почитать про него? Я знаю только один одно его исполнение - как для числовых операндов, но для чисел это добавление значения а не присваивание в прямом смысле. И если я комментирую строку с null, то внешне ничего не меняется, но я не уверен, что это правильно... Подскажите пожалуйста, как обнулить свойство Filter правильно.

  • Событие это делегат, а делегаты тоже имеют свою арифметику. Операция сложения добавляет новый делегат к многоадресному делегату, вычитание, соответственно, убирает. Я не думаю, что "прибавление" null к делегату - хорошая идея. Правильный способ обнуления делегата - "вычитание" из него всех "слагаемых". См. https://msdn.microsoft.com/ru-ru/library/ms366768.aspx
    • Изменено VadimTagil 4 мая 2017 г. 8:42
  • Вот именно об этом я и спрашивал. Отлично сказано - "своя арифметика", я только знаю, что операторы "+=" и "=" могут быть перегружены и для каждого типа работают по своему.

    Я ввел свойство класса filterEventHandler типа FilterEventHandler. В самый первый раз я его инициализирую:

     filterEventHandler = new FilterEventHandler(MyFilter);
                CollViewSource.Filter += filterEventHandler;

    А потом делаю так:

     CollViewSource.Filter -= filterEventHandler;
                    CollViewSource.Filter += filterEventHandler;

    Ошибок нет, внешне все так же, но мне кажется это более логичные действия.

  • Только мне все равно не нравится, подход в целом. Если Filter это подписка (событие), то оно должно выполняться всякий раз при каких-то условиях - тогда при каких? Или это такое специальное свойство, которое срабатывает один раз при его назначении?