Мерцание при обновлении элементов управления в WinForms (например, DataGridView)
В моем приложении у меня есть элемент управления DataGridView, который отображает данные для выбранного объекта. Когда я выбираю другой объект (в поле со списком выше), мне нужно обновить сетку. К сожалению, разные объекты имеют совершенно разные данные, даже разные столбцы, поэтому мне нужно очистить все существующие данные и столбцы, создать новые столбцы и добавить все строки. Когда это сделано, весь контроль мерцает ужасно, и это занимает целую вечность. Есть ли общий способ получить элемент управления в состоянии обновления, чтобы он не перекрашивался сам, а затем перекрасить его после того, как я закончу все обновления?
Это возможно с TreeViews:
myTreeView.BeginUpdate();
try
{
//do the updates
}
finally
{
myTreeView.EndUpdate();
}
Есть ли общий способ сделать это с другими элементами управления, в частности DataGridView?
ОБНОВЛЕНИЕ: Извините, я не уверен, что я был достаточно ясен. Я вижу "мерцание", потому что после однократного редактирования элемент управления перекрашивается на экране, поэтому вы можете видеть уменьшение полосы прокрутки и т. Д.
8 ответов
Вместо того, чтобы добавлять строки сетки данных по одной, используйте DataGridView.Rows.AddRange
способ добавить все строки одновременно. Это должно только обновить дисплей один раз. Там также есть DataGridView.Columns.AddRange
сделать то же самое для столбцов.
Люди, кажется, забывают простое исправление для этого:
Object.Visible = false;
//do update work
Object.Visible = true;
Я знаю, это кажется странным, но это работает. Когда объект не виден, он не будет перерисовываться. Вы все еще, однако, должны сделать begin
а также end
Обновить.
Элемент управления.NET поддерживает методы SuspendLayout и ResumeLayout. Выберите соответствующий родительский элемент управления (т. Е. Элемент управления, в котором размещены элементы управления, которые вы хотите заполнить) и выполните что-то вроде следующего:
this.SuspendLayout();
// Do something interesting.
this.ResumeLayout();
Двойная буферизация здесь не поможет, так как это только двойные буферы операций рисования, мерцание, которое видит OP, является результатом нескольких операций рисования:
- Очистить содержимое элемента управления -> перекрасить
- Очистить столбцы -> перекрасить
- Заполните новые столбцы -> перекрасить
- Добавить строки -> перекрасить
так что это четыре перекраски для обновления элемента управления, отсюда и мерцание. К сожалению, не все стандартные элементы управления имеют BeginUpdate/EndUpdate, который удалял бы все вызовы перерисовки, пока не будет вызван EndUpdate. Вот что вы можете сделать:
- Иметь разные элементы управления для каждого набора данных и показать / скрыть элементы управления,
- Удалите элемент управления из его родителя, обновите и снова добавьте элемент управления,
- Напишите свой собственный контроль.
Варианты 1 и 2 все равно будут немного мерцать.
В программе.Net GUI, над которой я работаю, я создал набор настраиваемых элементов управления, которые устраняют все мерцания.
Это сработало для меня.
http://www.syncfusion.com/faq/windowsforms/search/558.aspx
В основном это включает в себя получение от желаемого элемента управления и установку следующих стилей.
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
Похоже, вы хотите двойной буферизации:
http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx
Хотя это в основном используется для отдельных элементов управления, вы можете реализовать это в элементе управления Windows Forms или в форме.
К сожалению, я думаю, что Thins может быть просто побочным продуктом.net Framework. Я испытываю подобное мерцание, хотя с пользовательскими элементами управления. Многие из справочного материала, который я прочитал, указывают на это, наряду с тем фактом, что метод двойной буферизации не смог устранить мерцание для меня.
Вы также можете попробовать это, его работу.
public static void DoubleBuffered(Control formControl, bool setting)
{
Type conType = formControl.GetType();
PropertyInfo pi = conType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(formControl, setting, null);
}