0

我们有一个为用户创建任务窗格的 Microsoft EXCEL COM 插件。根据用户加载的“插件”,TaskPane 会填充相应的 UserControl,然后显示在屏幕上。

这些 UserControls 通常会涉及到 DataGridViews 的使用,我们保存用户选择了哪些行,这样每次加载插件时,已经为用户选择了之前选择的行。

但是,我们发现在将 UserControl 加载到 TaskPane 并使 TaskPane 可见的过程中,会触发几个外部代码方法,这会重置 datagridview 的选择。以下是这些事件:

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 中,它就不会保存这些值是没有意义的。

4

1 回答 1

0

正如您所诊断的,HandleCreated 事件清除了选择,因此解决方案是在您设置所选项目之前强制在您选择的时间创建句柄。这可以通过以下三种方法之一来完成:

  1. 参考控制手柄。如果尚未创建,这将强制它完成。
  2. 调用 Control.CreateHandle
  3. 调用 Control.CreateControl。这只会在 Control.Visible 属性为 True 时创建句柄。

@TnTinMn - 强制创建控件有效。...知道什么会导致延迟创建句柄吗?

要回答这个问题,我建议您参考来源。

所有关于 Windows 窗体中的句柄

控件何时创建其句柄?(控件何时调用 CreateWindowEx?)控件尽可能地尝试推迟创建其句柄。这是因为设置属性会强制 CLR 和 user32 之间进行聊天互操作。

通常,所有控件的句柄都是在调用 Form.Load 事件之前创建的。如果调用了“Handle”属性并且尚未创建句柄,或者调用了 CreateControl(),也可以创建句柄。

于 2015-10-27T18:05:28.880 回答