Производительность WPF Datagrid
Я работаю с сеткой данных WPF Toolkit, и в настоящий момент она прокручивается очень медленно. В сетке 84 столбца и 805 строк. (Включая 3 фиксированных столбца и заголовок фиксирован.) Прокрутка как по горизонтали, так и по вертикали чрезвычайно медленная. Виртуализация включена, и я включил виртуализацию столбцов и виртуализацию строк явно в xaml. Есть ли что-то, что можно было бы наблюдать за тем, что может реально повлиять на производительность, например, методы привязки или то, что xaml находится в каждом шаблоне celltemplate?
Следует отметить, что я динамически добавляю столбцы в создание datagrid. Может ли это что-то сделать? (Я также динамически создаю celltemplate в то же время, чтобы мои привязки были установлены правильно.)
Ниже приведен код шаблона для большинства генерируемых ячеек. В основном для столбцов, которые мне нужно динамически добавлять (это большинство из них), я просматриваю список и добавляю столбцы с помощью метода AddColumn, а также динамически строю шаблон, чтобы операторы привязки правильно индексировали нужный элемент в коллекции для этой колонки. Шаблон не слишком сложный, всего два блока TextBlocks, но я привязываю к ним по четыре разных свойства. Похоже, я смог выжать немного больше производительности, изменив привязки к OneWay:
private void AddColumn(string s, int index)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = s;
//Set template for inner cell two rectangles
column.CellTemplate = CreateFactViewModelTemplate(index);
//Set Style for header, ie rotate 90 degrees
column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
column.Width = DataGridLength.Auto;
dgMatrix.Columns.Add(column);
}
//this method builds the template for each column in order to properly bind the rectangles to their color
private static DataTemplate CreateFactViewModelTemplate(int index)
{
string xamlTemplateFormat =
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay}"" />
<TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay}"" />
</Grid>
</DataTemplate>";
string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());
return (DataTemplate)XamlReader.Parse(xamlTemplate);
}
Ответы
Ответ 1
Поскольку я не вижу ваш исходный код, вам очень сложно помочь. Тем более, что на производительность приложения WPF влияет множество вещей. Для некоторых советов о том, что следует искать, см. Оптимизация производительности приложения WPF. И да - это очень важно, какой xaml используется в каждой ячейке. Потому что обычно проблемы с производительностью сводятся к "слишком большому количеству элементов". Знаете ли вы, что TextBox я считаю 30 отдельных элементов? Я рекомендую вам использовать Performance Profiling Tools для WPF, чтобы узнать больше о вашей конкретной проблеме. Постарайтесь минимизировать количество элементов, которые вы используете (например, переключаясь с TextBox на TextBlock, если это необходимо).
Также вы должны проверить, существуют ли проблемы с производительностью на любом ПК, на котором вы пытаетесь включить приложение. Возможно, ПК, который вы используете, заставляет WPF в программном рендеринге. Или вы используете BitmapEffects?
Edit:
Глядя на свой код, я предлагаю вам изменить
column.Width = DataGridLength.Auto;
до разумной фиксированной ширины, так как datagrid не должен динамически пересчитывать ширину каждый раз, когда что-то изменяется (например, добавление строк или даже прокрутка).
Ответ 2
Общий совет для проблем производительности DataGrid: у меня была проблема с DataGrid, в которой потребовалось буквально секунд, чтобы обновить после изменения размера окна, сортировки столбцов и т.д. и заблокировал пользовательский интерфейс окна, когда он это делал (1000 строк, 5 столбцов).
Это привело к проблеме (ошибка?) с расчетами размера WPF. Я имел это в сетке с RowDefinition Height = "Auto", которая заставляла систему рендеринга попробовать и пересчитать размер DataGrid во время выполнения, измеряя размер каждого столбца и строки, предположительно, заполнив всю сетку ( как я понимаю). Он должен воспринимать это разумно каким-то образом, но в этом случае это не так.
Быстрая проверка, чтобы убедиться, что это связанная с этим проблема, заключается в том, чтобы установить значения высоты и ширины DataGrid на фиксированный размер в течение всего теста и повторить попытку. Если ваша производительность восстановлена, среди этих опций может быть постоянное исправление:
- Измените размеры содержащихся элементов как относительные (*) или
фиксированные значения
- Установите MaxHeight и MaxWidth DataGrid на фиксированное значение больше
чем он может нормально работать.
- Попробуйте использовать другой тип контейнера с другой стратегией изменения размера (Grid, DockPanel и т.д.).
Ответ 3
в одном из моих проектов следующая настройка стиля сетки вызывала серьезную проблему с производительностью:
<Style TargetType='{x:Type controls:DataGrid}'>
<Setter Property='ScrollViewer.CanContentScroll' Value='False' />
...
Когда я удалил параметр ScrollViewer.CanContentScroll, проблема с производительностью исчезла.
Ответ 4
Есть ли у вас какой-либо планшет любого типа (через USB или планшетный ПК)?
Я обнаружил ошибку производительности в WPat datagrid при использовании планшета. Я разместил видео, и он подтвержден MS здесь, в этом потоке
Cheers,
Джон
Ответ 5
У меня был случай, когда мой базовый объект имел свойство только с установщиком. Такое же свойство было доступно путем реализации ITypedList в коллекции и через TypeDescriptionProvider/ICustomTypeDescriptor для отдельных объектов. Либо удаление свойства, либо добавление геттера разрешили проблемы с производительностью.
Ответ 6
Одна вещь, которую я хотел бы предложить в таких сценариях, - это посмотреть, как вы применяли стиль и каков стиль в каждой ячейке.
Стиль, применяемый, если он имеет сложное визуальное дерево, имеет тенденцию ухудшать производительность.
Вы также можете попробовать опцию "Отложенная прокрутка" в последнем WPat Datagrid.