Низкая производительность при горизонтальной прокрутке в сетке данных WPF4


У меня есть приложение, которое должно отображать сетку данных, состоящую в основном из булевых значений, и столбцы флажков подходят для счета. Там будет около 40-60 столбцов чекбокса с примерно 200 строками. Я думал, что было бы тривиально сделать что-то подобное в WPF.

Я не могу даже приблизиться к приличному опыту горизонтальной прокрутки с WPF. Чтобы понять, о чем я говорю, создайте Window и поместите на него DataGrid, а затем установите AutoGenerateColumns="True", а затем добавьте следующее в конструктор после InitializeComponent();:

dataGrid1.ItemsSource = Create(200, i => new { b1 = true, b2 = false, b3 = true, b4 = false, b5 = true, b6 = false, b7 = true, b8 = false, b9 = true,
                                               b10 = false, b11 = true, b12 = false, b13 = true, b14 = false, b15 = true, b16 = false, b17 = true, b18 = false, b19 = true, b20 = false, b21 = true,
                                               b22 = false, b23 = true, b24 = false, b25 = true, b26 = false, b27 = true, b28 = false, b29 = true, b30 = false, b31 = true, b32 = false });

Требуется этот метод, добавьте его тоже:

ObservableCollection<T> Create<T>(int count, Func<int, T> creator)
{
    return new ObservableCollection<T>(Enumerable.Range(0, count).Select(creator));
}

Запустите приложение и попытайтесь прокрутить его по горизонтали. Ужасно, не правда ли? Вертикальная прокрутка тоже не слишком горячая.

Я сделал то же самое с приложением WinForms, и прокрутка была гладкой во всех направлениях, и выглядела так же хорошо, как WPF после принудительного использования свойства DataGridView DoubleBuffered в true. Чтобы сравнить, создайте новый Form, хлопните a DataGridView и добавьте в конструктор следующее после InitializeComponent();:

typeof(DataGridView).GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(dataGridView1, true, null);
for (int i = 0; i < 64; i++)
    dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn {HeaderText = "C" + i, Width = 30});
for (int i = 0; i < 400; i++)
    dataGridView1.Rows.Add();
У него вдвое больше столбцов, вдвое больше строк, и он прокручивается гладко, как дно новорожденного, как по горизонтали, так и по вертикали. Но, к сожалению, я не могу сделать то, что мне нужно с WinForms. Мне нужны шаблонные колонки. Мне нужна композиционность.

Чтобы решить проблему прокрутки в WPF, я попробовал все комбинации следующего:

  • EnableColumnVirtualization (true / false)
  • EnableRowVirtualization (true / false)
  • ScrollViewer.CanContentScroll (true / false) - false улучшает только вертикальную прокрутку
  • столбцы фиксированного размера
  • сетка данных фиксированного размера
  • VirtualizingStackPanel.VirtualizationMode (рециркуляция / стандарт) - Recycling есть ошибка, при которой он будет повторно использовать элемент управления CheckBox, который проверен и помещает его в новую строку, где он должен быть снят, вызывая затухание анимации. Это заставляет флажки казаться " призрачными" эффект.
  • ScrollViewer.IsDeferredScrollingEnabled-извините, но я не могу принять понижение до Windows 3.1-стиль прокрутки для чего-то настолько тривиального.

Я готов принять некачественное исполнение. Я не ожидаю ничего подобного гладкости WinForms (WPF в конце концов дает мне гораздо больше, хотя это должно было быть компенсировано ускорением GPU WPF). Я просто хочу что-то полезное, даже почти бесполезное.

2 2

2 ответа:

Как указано в моем комментарии, я не уверен в вопросе. Если вы ищете производительность сетки в WPF, то перейдите в ListView / GridView. Если только нет какой-то особенности DataGrid, которую вы должны иметь. Это больше кода, но оно того стоит. У меня есть GridView с 40 столбцами и 1000 строк и хорошей производительностью (а производительность DataGrid была плохой).

Это в основном потому, что визуальное дерево CheckBox довольно сложное. Вы можете получить намного лучшую производительность, если вы перестроите визуальное дерево.

Имея только один элемент в ControlTemplate (single border), не было никакой задержки или задержки. Вы можете получить определенный стиль отсюда: http://msdn.microsoft.com/en-us/library/ms752319%28v=vs.85%29.aspx

Наверняка будет потрачено некоторое время на привязку данных. Видеть это: оптимизация привязки данных , она объясняет, что привязка на обычное имущество уходит больше времени. Обычно потому, что это предполагает рефлексию. При использовании свойств зависимостей отражение не требуется. Насколько мне известно.

Ваш класс, безусловно, не большой,но вы, конечно, можете проверить. Будет ли он работать лучше, если все будет свойством зависимости?

Дайте мне знать, если у вас возникнут какие-либо проблемы.