Search code examples
vb.neteventsdatagridviewtabcontroltabpage

Update DataGridView but do not select any rows when TabPage entered


I have a DataGridView on a secondary TabPage, and I would like the data inside the grid to update when the TabPage is entered, but I do not want the RowEnter event to be handled unless the user actually clicked on a row. It seems that the first row in the grid is auto-selected AFTER the TabPage.Enter event fires, so I am having trouble suppressing it.

Code showing the problem is below. I have created the controls at runtime so you can just copy-paste, but in the actual program I used the Designer.

The behaviour I would like to see is that after selecting TabPage2, the DataGridViewis full of data, but TextBox1 is empty, until I click on a row.

Public Class Form1

  Private WithEvents DataGridView1 As DataGridView
  Private WithEvents TextBox1 As TextBox
  Private WithEvents TabPage2 As TabPage
  Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

    'Add controls to the form (usually I use the designer to do this)
    Dim TabPage1 As New TabPage() With {.Name = "TabPage1", .Text = "TabPage1"}
    TabPage2 = New TabPage() With {.Name = "TabPage2", .Text = "TabPage2"}
    DataGridView1 = New DataGridView With {.Name = "DataGridView1", .SelectionMode = DataGridViewSelectionMode.FullRowSelect, .MultiSelect = False, .ReadOnly = True, .AllowUserToAddRows = False, .Size = New Size(TabPage1.Size.Width, TabPage2.Size.Height - 40), .Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom, .TabIndex = 1}
    TextBox1 = New TextBox With {.Name = "TextBox1", .Top = DataGridView1.Bottom + 5, .Width = DataGridView1.Width, .Visible = True, .Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom, .TabIndex = 0}
    TabPage2.Controls.Add(TextBox1)
    TabPage2.Controls.Add(DataGridView1)
    Dim TabControl1 As New TabControl() With {.Name = "TabControl1"}
    TabControl1.TabPages.Add(TabPage1)
    TabControl1.TabPages.Add(TabPage2)
    TabControl1.Size = Me.ClientRectangle.Size
    TabControl1.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom
    Me.Controls.Add(TabControl1)
  End Sub

  Private Sub DataGridView1_RowEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowEnter
    'I would like the textbox to fill ONLY after the user has selected a row in DataGridView1. 
    'The problem I am having is that the first row auto-selects once I enter the tab
    Dim drw As DataRow = DirectCast(DataGridView1.Rows(e.RowIndex).DataBoundItem, DataRowView).Row
    TextBox1.Text = CStr(drw(1))
  End Sub

  Private Sub TabPage2_Enter(sender As Object, e As EventArgs) Handles TabPage2.Enter
    RefreshGrid() 'Refresh the data in the list    
  End Sub

  Sub RefreshGrid()
    'simulate a database query 
    DataGridView1.DataSource = Nothing
    Dim dtb As New DataTable
    dtb.Columns.Add("C1")
    dtb.Columns.Add("C2")
    dtb.Rows.Add("1", "One")
    dtb.Rows.Add("2", "Two")
    dtb.Rows.Add("3", "Three")
    dtb.Rows.Add("4", "Four")
    dtb.Rows.Add("5", "Five")
    DataGridView1.DataSource = dtb
  End Sub

End Class

Solution

  • From the TabPage documentation Remarks section

    Controls contained in a TabPage are not created until the tab page is shown, and any data bindings in these controls are not activated until the tab page is shown.

    Since you binding the DataGridView in the TabPage.Enter event to a new DataTable, you can use the DataGridView.DataBindingComplete event to clear the default selection.

    Private Sub DataGridView1_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
        TextBox1.Clear()
        DataGridView1.ClearSelection()
    End Sub