0

We have an Microsoft EXCEL COM Addin that creates a TaskPane for the user. Based on the "plug-in" that the user loads, the TaskPane is populated with a corresponding UserControl and then displayed on the screen.

These UserControls typically involve the use of DataGridViews, and we save which rows the user has selected, so that each time the plug-in is loaded, the previously selected rows are already selected for the user.

However, what we have found is that in the process of loading the UserControl onto the TaskPane, and making the TaskPane visible, several external code methods fire, which reset the selection of the datagridview. Below are those events:

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

The actual code is more complex and involves calls to a database, but as an example, this shows how we create the DGV and then populate and select the rows. The below code would follow the InitializeComponents() method in the constructor of the 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

We do not want to move the process of selecting the rows AFTER the TaskPane is visible, because the user will see the changes, and is not a clean look for the end user. It makes no sense that an instantiated DGV object with selected rows would not hold those values once it is added to a TaskPane.

Thrifty2100
  • 105
  • 1
  • 8
  • I think you are experiencing a consequence of delayed handle creation on controls. Try calling dgvExample.CreateControl after InitializeComponents, but before your setting of the selected rows. – TnTinMn Oct 27 '15 at 16:08
  • In addition to my above recommendation you may need to call dgvExample.CreateHandle if dgvExample.Visible = False. – TnTinMn Oct 27 '15 at 16:23
  • @TnTinMn - Forcing the creation of the control worked. This is a simple and effective solution. I also considered building a class that inherits DataGridView, and Overriding the OnHandleCreated method: I would store the selected rows, call the MyBase.OnHandleCreated(e) method and then re-select the rows. Any idea what can cause delayed handle creation? – Thrifty2100 Oct 27 '15 at 17:50

1 Answers1

0

As you had diagnosed, the HandleCreated event clears the Selection, so the solution is force the handle to be created at a time of your choosing before you set the selected items. This can be accomplished by one of three methods:

  1. Reference the control handle. If not yet created, this will force it to be done.
  2. Call Control.CreateHandle
  3. Call Control.CreateControl. This will only create the handle if the Control.Visible property is True.

@TnTinMn - Forcing the creation of the control worked. ... Any idea what can cause delayed handle creation?

To answer this I refer you to the source.

All About Handles in Windows Forms

When does a Control create its handle? (When does a control call CreateWindowEx?) A control tries as much as possible to defer creating its handle. This is because setting properties forces chatty interop between the CLR and user32.

Typically the handles for all the controls are created before the Form.Load event is called. Handles can also be created if the "Handle" property is called and the handle has not yet been created, or CreateControl() is called.

TnTinMn
  • 11,522
  • 3
  • 18
  • 39