DataGridView Handle OnHandleCreate Сброс выбранных строк

У нас есть надстройка Microsoft EXCEL COM, которая создает панель задач для пользователя. В зависимости от «подключаемого модуля», который загружает пользователь, панель задач заполняется соответствующим элементом управления UserControl, а затем отображается на экране.

Эти пользовательские элементы управления обычно включают использование DataGridViews, и мы сохраняем, какие строки выбрал пользователь, так что каждый раз, когда подключаемый модуль загружается, ранее выбранные строки уже выбраны для пользователя.

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

System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnSelectionChanged(System.EventArgs e) + 0x88 bytes   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.FlushSelectionChanged    () + 0x37 bytes  
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.ClearSelection(int columnIndexException, int rowIndexException, bool selectExceptionElement) + 0x304 bytes    
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.SetAndSelectCurrentCellAddress(int columnIndex, int rowIndex, bool setAnchorCellAddress, bool        validateCurrentCell, bool throughMouseClick, bool clearSelection, bool forceCurrentCellSelection) + 0x60 bytes   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.MakeFirstDisplayedCellCurrentCell(bool includeNewRow) + 0x88 bytes    
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnHandleCreated(System.EventArgs e) + 0x3d bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.WmCreate(ref System.Windows.Forms.Message m) + 0x43 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x2ed bytes  
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.WndProc(ref System.Windows.Forms.Message m) + 0x10a bytes     
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x11 bytes     
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x39 bytes       System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x5e bytes

Фактический код более сложен и включает вызовы базы данных, но в качестве примера здесь показано, как мы создаем DGV, а затем заполняем и выбираем строки. Код ниже будет следовать методу InitializeComponents() в конструкторе UserControl:

dgvExample.Rows.Add("Actuals") 
dgvExample.Rows.Add("Budget") 
dgvExample.Rows.Add("Forecast") 
dgvExample.Rows.Add("LY Actuals") 

For i = 0 To dgvExample.Rows.Count - 1 
   dgvExample.Rows(i).Selected = True 
Next

Мы не хотим перемещать процесс выбора строк ПОСЛЕ того, как TaskPane станет видимым, потому что пользователь увидит изменения, а не чистый вид для конечного пользователя. Нет никакого смысла в том, что экземпляр объекта DGV с выбранными строками не будет содержать эти значения после его добавления в TaskPane.


person Thrifty2100    schedule 27.10.2015    source источник
comment
Я думаю, что вы испытываете последствия задержки создания дескриптора на элементах управления. Попробуйте вызвать dgvExample.CreateControl после InitializeComponents, но перед настройкой выбранных строк.   -  person TnTinMn    schedule 27.10.2015
comment
В дополнение к моей приведенной выше рекомендации вам может потребоваться вызвать dgvExample.CreateHandle, если dgvExample.Visible = False.   -  person TnTinMn    schedule 27.10.2015
comment
@TnTinMn - сработало принудительное создание элемента управления. Это простое и эффективное решение. Я также рассматривал возможность создания класса, наследующего DataGridView, и переопределения метода OnHandleCreated: я сохранял выбранные строки, вызывал метод MyBase.OnHandleCreated(e), а затем повторно выбирал строки. Любая идея, что может вызвать задержку создания дескриптора?   -  person Thrifty2100    schedule 27.10.2015


Ответы (1)


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

  1. Ссылка на дескриптор управления. Если он еще не создан, это заставит его сделать.
  2. Call Control.CreateHandle
  3. Вызов Control.CreateControl. Это создаст дескриптор только в том случае, если свойство Control.Visible имеет значение True.

@TnTinMn - сработало принудительное создание элемента управления. ... Любая идея, что может вызвать задержку создания дескриптора?

Чтобы ответить на это, я отсылаю вас к источнику.

Все об дескрипторах в Windows Forms

Когда элемент управления создает свой дескриптор? (Когда элемент управления вызывает CreateWindowEx?) Элемент управления максимально старается отсрочить создание своего дескриптора. Это связано с тем, что установка свойств приводит к диалоговому взаимодействию между CLR и user32.

Обычно дескрипторы для всех элементов управления создаются до вызова события Form.Load. Дескрипторы также могут быть созданы, если вызывается свойство "Handle", а дескриптор еще не создан, или вызывается CreateControl().

person TnTinMn    schedule 27.10.2015