Подтвердить что ты не робот

Виртуализация WPF DataGrid с группировкой

Я использую WPF DataGrid из CodePlex, и мне нужно заставить виртуализацию работать с группировкой.

Этот question находится в теме и указывает на Пример MSDN но он охватывает только ListControls с помощью простых (то есть одиночных "столбцов" ) DataTemplates.

Группировка и виртуализация кажутся довольно распространенным прецедентом для Grid. Есть ли стандартный/рекомендуемый/простой способ добиться этого?

4b9b3361

Ответ 1

Я понимаю, что опаздываю на вечеринку здесь... но я столкнулся с этой проблемой недавно (используя DataGrid, встроенный в .NET 4). К сожалению, до сих пор нет виртуализации строк после того, как Grouping используется в DataGrid... но я нашел очень гладкий трюк повышения производительности, который, надеюсь, кто-то еще найдет полезным.

Предполагая, что вы используете ItemPresenter в расширителе вашего шаблона GroupItem, и по умолчанию ваш расширитель не расширяется, а затем попробуйте просто привязать видимость вашего ItemsPresenter к свойству Expander IsEnabled с помощью BooleanToVisibilityConverter по умолчанию:

<BooleanToVisibilityConverter x:Key="bool2vis" />


<DataGrid.GroupStyle>
    <GroupStyle>
        <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GroupItem}">
                            <Expander x:Name="exp">
                                <ItemsPresenter Visibility="{Binding ElementName=exp, Path=IsExpanded, Converter={StaticResource bool2vis}}" />
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </GroupStyle.ContainerStyle>
    </GroupStyle>
</DataGrid.GroupStyle>

Если вы столкнулись с проблемой, когда ваш DataGrid занимает очень много времени для загрузки (потому что он по существу вытаскивает каждую запись в вашем datagrid, даже если он в сложенном расширителе)... тогда использование вышеуказанного кода приведет к тому, что datagrid чтобы не рисовать свои записи до тех пор, пока вы не разберете группу, а затем вытащите записи только для этой группы.

Нижняя сторона заключается в том, что это помогает только в том случае, если ваши расширители сбрасываются по умолчанию, и все же строки не становятся виртуализированными (если у вас есть 100 элементов в расширенной группе, но только 20 подходят на экране, все 100 будут в то время, когда вы расширили группу).

Положительный момент заключается в том, что вы по существу выполняли ленивую загрузку своих записей DataGrid, поэтому вы не выполняете работу с рисунком, пока вам не нужно будет просматривать элементы (вы решили расширить группу). Для моего продукта у моего заголовка группы были встроенные кнопки для выполнения операций над всеми элементами в своей группе, поэтому чаще пользователь никогда не расширил группу, если только им не нужно было выполнять операцию над отдельным элементом внутри группы.

* Следует отметить, что если вы используете этот трюк, вы должны, вероятно, установить некоторые явные ширины или минимальную ширину в заголовки столбцов (потому что элементы не рисуются при первом загрузке DataGrid, поэтому заголовки столбцов не могут авторизоваться соответствует самому большому элементу).

Надеюсь, настоящая виртуализация будет реализована в будущем пакете обновлений, но если нет, я надеюсь, что это поможет кому-то еще!

Update

Похоже, эта проблема будет исправлена ​​в .NET 4.5 с новым прикрепленным свойством VirtualizingPanel.IsVirtualizingWhenGrouping.

Ответ 2

В фреймворке 4.5 VirtualizingPanel.IsVirtualizingWhenGrouping есть новое добавленное свойство, которое позволяет включать виртуализацию при группировке.

<DataGrid EnableColumnVirtualization="True" EnableRowVirtualization="True"
   VirtualizingPanel.IsVirtualizingWhenGrouping="True">

Ответ 3

Нет встроенной функции, которая позволяет включать виртуализацию пользовательского интерфейса, если группировка включена в ListView или DataGrid. Если вы думаете об этом на секунду, это также имеет смысл. Как DataGrid группировать элементы, которые не существуют. Чтобы применить группировку элемента управления, необходимо будет загрузить всю коллекцию, которая победит всю цель виртуализации. Лучшее, что вы, вероятно, можете сделать, это предоставить некоторую виртуализацию в вашей модели viewmodel (объект, который вы связываете снова), в том, что вы предоставляете только те данные, которые в настоящее время нужны, а также какие-то общие данные о количестве данных, которые существуют, а затем поддельные представление себя.

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

Ответ 4

Как вы сказали, включение Grouping отключит виртуализацию пользовательского интерфейса.

Я не думаю, что вы найдете простой способ решить эту проблему. Я бы рекомендовал вам проверить один из доступных WPF DataGrid, например XCeeed, который может иметь эту функцию, встроенную в их управление.