WPF CollectionViewSource.Filter Performance v. DataTrigger - PullRequest
0 голосов
/ 25 августа 2011

Entity Framework предоставляет отслеживаемые объекты, которые имеют свойство с именем ChangeTracker.State. Используя это, мы можем определить, удалена ли сущность.

В нашем списке мы НЕ хотим показывать удаленные объекты.

Что быстрее?

Метод 1: Использование CollectionViewSource.Filter для тестирования и удаления записи

<CollectionViewSource Filter="ViewSource_Filter" />

private void ViewSource_Filter(object sender, FilterEventArgs e)
{
    var _Item = e.Item as ITrackableEntity;
    e.Accepted = _Item.ChangeTracker.State != ObjectState.Deleted;
}

Метод 2: Добавление DataTrigger к ItemTemplate.DataTemplate для проверки и скрытия элемента

<DataTemplate.Resources>
    <Style TargetType="{x:Type DockPanel}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ChangeTracker.State}">
                <DataTrigger.Value>
                    <entities:ObjectState>Deleted</entities:ObjectState>
                </DataTrigger.Value>
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataTemplate.Resources>

Спасибо.

Ответы [ 3 ]

2 голосов
/ 26 августа 2011

Предполагая, что с этой проблемой связан ItemsControl, мне лично нравится фильтр на основе коллекции.

Причины ...

  1. Его фильтрация находится в руках ViewModel.Поэтому, когда бы он ни захотел обновить представление коллекции, он будет повторно фильтроваться снова.

  2. Если свойство ChangeTracker.State заполняется и не обновляется в течение всего жизненного цикла пользовательского интерфейса, тогда представление коллекциибудет фильтровать только один раз при рендеринге.DataTriggers, с другой стороны, будут ожидать любых изменений в ChangeTracker.State, которые могут / не могут произойти.

  3. Чередующиеся элементы Строковые стили для ItemsControl, к которому применяется это CollectionView, не будутПримените правильный эффект с помощью триггера данных, потому что он будет только скрывать элементы и не будет корректировать альтернативные стили строк, но коллекционное представление заранее исключит элементы.т.е. если альтернативные строки должны быть серого фона, то может случиться так, что две соседние строки будут серыми, если используется DataTrigger.

  4. DataTriggers вступят в силу ТОЛЬКО для не витализированных элементов из-заЭвристика полосы прокрутки может быть испорчена, например, если представление прокрутки показывает только 10 видимых элементов, и в источнике есть 90 элементов, но 50 находятся в состоянии Deleted, их триггер данных не вступит в силу, пока мы не выделим их.Таким образом, при этом полоса прокрутки пересчитывается и мерцает для корректировки фактического значения прокрутки.Так что может показаться, что у нас есть 100 пунктов для прокрутки, тогда как на самом деле для прокрутки нужно всего 50 пунктов.

CollectionView предоставляет 50 элементов для просмотра с прокруткой перед самой рукой.

Таким образом, благодаря производительности, DataTrigger будет работать быстрее из-за того, чтоприменить только применить, когда элемент де-виртуализирован, то есть внесен в представление прокрутки.Но это может поставить вышеупомянутые проблемы.

Дайте мне знать, если это поможет.

0 голосов
/ 08 сентября 2011

Метод 1 - правильный ответ.

0 голосов
/ 25 августа 2011

Но событие Loaded может содержать необходимую информацию. Из MSDN: событие Loaded вызывается до окончательного рендеринга, но после того, как система макета рассчитала все необходимые значения для рендеринга. Загруженный влечет за собой, что логическое дерево, в котором содержится элемент, является полным, и соединяется с источником представления, который обеспечивает HWND и поверхность рендеринга. Моя интерпретация состоит в том, что фильтры и триггеры были обработаны, но я не уверен. Unloaded не является окончательным числом, но я думаю, вы бы сравнили яблоки с яблоками. Но все же яблоки не могут быть правильным сравнением. Было бы так здорово, если бы отладчик прошел XAML. Поскольку отладчик не проходит XAML, я просто не думаю, что вы можете непосредственно измерить триггер. Лучшая надежда - измерить страницу. Создайте страницу без сложного фильтра.

    public MainWindow()
    {
        Debug.WriteLine(DateTime.Now.ToLongTimeString());
        InitializeComponent();
        Debug.WriteLine(DateTime.Now.ToLongTimeString());
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine(DateTime.Now.ToLongTimeString());

Отладка - это не то же самое, что прямое выполнение, поэтому я бы связал эти 3 раза с TextBlocks. И я бы также сравнил с фильтром, определенным в XAML. Я чувствую, что оба будут настолько быстрыми, что трудно понять разницу, но я предполагаю, что фильтр работает быстрее.

...