Сам фильтр предельно простой: (obj) => obj.Property == true (к примеру). Ну то есть тормозить тут вообще нечему!
Что не нравится: КРАЙНЕ долгая фильтрация даже на 6 элементах!! Кликаю чекбокс, а список обновляется после секунды(!) фильтрации — почему так долго-то?? Подумаешь — Func сконструировал!
Вот не пойму, куда тут вообще копать. Может, грид можно как-то зафорсить "перефильтровать" чем-то помимо Refresh()? (если влиял именно он)
PS
Делал и без всяких хелперов — прям с формы делал GetDefaultView, назначал фильтр — та же медленная петрушка, т.е. дело точно не в Func/лямбдах.
Сам нашёл затык, но думаю, многим тоже будет полезно. А дело было... в перекрытом Equals!!
public override bool Equals(object obj)
{
var b2 = (Beacon)obj;
if (b2 == null) return false;
return ID != 0 && ID == b2.ID;
}
Вот эта зараза сразу просадила производительность до целой секунды на смешных 6 элементах — это как вообще?!
Но возникает другой вопрос: каким боком Equals к фильтрации?? Я же сам задаю критерий фильтрования!
К слову: может, что-то не так/медленно/неэффективно в самом Equals? Я его делал для записей СУБД, где очевидно, что если ID равны, то это один и тот же объект и нет смысла сравнивать поля.
K>public override bool Equals(object obj)
K>{
K> var b2 = (Beacon)obj;
K> if (b2 == null) return false;
K> return ID != 0 && ID == b2.ID;
K>}
K>
.. K>К слову: может, что-то не так/медленно/неэффективно в самом Equals? Я его делал для записей СУБД, где очевидно, что если ID равны, то это один и тот же объект и нет смысла сравнивать поля.
Безотносительно тормозов в фильтрации грида (хз какого ), выделенное условие никогда не сработает (точнее сработает если obj == null), т.к. если obj не приводится к Beacon, то при касте будет исключение. Обычно проверяют через as: obj as Beacon.
Здравствуйте, Kolesiki, Вы писали:
K>Эврика!
K>Сам нашёл затык, но думаю, многим тоже будет полезно. А дело было... в перекрытом Equals!!
K>
K>public override bool Equals(object obj)
K>{
K> var b2 = (Beacon)obj;
K> if (b2 == null) return false;
K> return ID != 0 && ID == b2.ID;
K>}
K>
По гайдлайнам при перекрытии Equals должен быть переопределен оператор сравнения. Значит, проверка b2 == null пойдет в него.
K>Вот эта зараза сразу просадила производительность до целой секунды на смешных 6 элементах — это как вообще?! K>Но возникает другой вопрос: каким боком Equals к фильтрации?? Я же сам задаю критерий фильтрования!
K>К слову: может, что-то не так/медленно/неэффективно в самом Equals? Я его делал для записей СУБД, где очевидно, что если ID равны, то это один и тот же объект и нет смысла сравнивать поля.
Чисто версия. Если ID изменяемый, то он может ломать сравнение элементов. От этого может страдать производительность (и не только).
вообще, обычно делают наоборот, т.е. сначала заворачивают данные в CollectionViewSource, а потом уже dataView используют как источник в других контролах:
по-идее, если так фильтровать, то Refresh уже не надо вызывать, фильтр автоматически применится. Refresh вызывают, когда надо пересоздать вью по какой-то причине.
Здравствуйте, pilgrim_, Вы писали:
K>>public override bool Equals(object obj) K>>{ K>> var b2 = (Beacon)obj; K>> if (b2 == null) return false;
_>... выделенное условие никогда не сработает (точнее сработает если obj == null), т.к. если obj не приводится к Beacon, то при касте будет исключение. Обычно проверяют через as: obj as Beacon.
В моём случае за это можно не беспокоиться — сравнение применяется исключительно для Beacon объектов. Вопрос, за каким якодзуном WPF понадобился этот метод вообще?? Фильтрация грида — там мой кастомный фильтр, никаких Equals не вызывается.
Здравствуйте, notacat, Вы писали:
N>вообще, обычно делают наоборот, т.е. сначала заворачивают данные в CollectionViewSource, а потом уже dataView используют как источник в других контролах:
N>
N>по-идее, если так фильтровать, то Refresh уже не надо вызывать, фильтр автоматически применится. Refresh вызывают, когда надо пересоздать вью по какой-то причине.
Разве при присвоении к ItemsSource не создаётся автоматически DefaultView? (который я потом и получаю)
И фильтр не должен автоматически применяться — ведь грид не знает, от каких контролов зависит фильтр.
N>>по-идее, если так фильтровать, то Refresh уже не надо вызывать, фильтр автоматически применится. Refresh вызывают, когда надо пересоздать вью по какой-то причине.
K>Разве при присвоении к ItemsSource не создаётся автоматически DefaultView? (который я потом и получаю) K>И фильтр не должен автоматически применяться — ведь грид не знает, от каких контролов зависит фильтр.
проблема не в создании DefaultView, а в том, что если ваш грид и другие контролы были бы прибайндены к одному CollectionView, то условия фильтрации жили бы в этом CollectionView, и все контролы бы их просто использовали. Гриду вообще не надо знать, от каких контролов эти условия зависят. Он бы просто ловил изменения условий бесплатно для вас. А так вы руками все туда-сюда копируете, да еще рефрешите, конечно долго. Что на самом деле делает DataGrid с вашим источником данных, если он не CollectionView, слишком глубоко закопано. В принципе, гриды обычно в таких случаях ваш источник заворачивают во что-то, с чем удобно работать. Дополнительные накладные расходы, скорей всего еще один CollectionView
В смысле производительности гораздо дешевле создать нормальный источник, и забайндить его везде, чтобы грид с ним напрямую работал
N>>>по-идее, если так фильтровать, то Refresh уже не надо вызывать, фильтр автоматически применится. Refresh вызывают, когда надо пересоздать вью по какой-то причине.
K>>Разве при присвоении к ItemsSource не создаётся автоматически DefaultView? (который я потом и получаю) K>>И фильтр не должен автоматически применяться — ведь грид не знает, от каких контролов зависит фильтр.
N>проблема не в создании DefaultView, а в том, что если ваш грид и другие контролы были бы прибайндены к одному CollectionView....
Шта?? К коллекции прибайнден только грид.
N>, то условия фильтрации жили бы в этом CollectionView
Они и так там живут! Я же фильтр указал — он всегда и вызывается, ничего не пересоздаётся.
N>Гриду вообще не надо знать, от каких контролов эти условия зависят. Он бы просто ловил изменения условий бесплатно для вас
КАК? У меня текстовое поле, комбобокс, чекбоксы, радиобатоны... как он их будет отслеживать? Я делаю ровно наоборот — при изменении в фильтрующих контролах даю гриду команду "обновись".
N> А так вы руками все туда-сюда копируете, да еще рефрешите, конечно долго
Что именно копирую?? Рефрешу — да, но грид по-любому должен рефрешиться, как иначе он отфильтрует данные??
N> Что на самом деле делает DataGrid с вашим источником данных, если он не CollectionView, слишком глубоко закопано. В принципе, гриды обычно в таких случаях ваш источник заворачивают во что-то, с чем удобно работать.
Ну да. в DefaultView! Какой смысл мне его создавать, если грид и так его сделает??
N> Дополнительные накладные расходы, скорей всего еще один CollectionView
Нет никаких дополнительных — всё тот же вью, который грид создал под капотом.
N>В смысле производительности гораздо дешевле создать нормальный источник, и забайндить его везде, чтобы грид с ним напрямую работал
Список и есть "нормальный источник", мне не нужно лезть в потроха грида (или другого списочного элемента). Собственно, нам для этого и выставили ItemsSource, чтобы мы туда напрямую присваивали наши коллекции, не заботясь о деталях реализации.