ComboBox 在加载到新表单时显示第一项 VB.Net

ComboBox shows the first item when loaded into new form VB.Net

我有两个连接的表单,第一个有一个 datagridview(DGV),它将显示员工列表。

当我双击该行时,FGV 中的数据将转换为第二种形式,供用户编辑数据。 DGV 中的每一列都将插入到文本框组合框等处。

但是当我双击 DGV 时,第二种形式的组合框正在使用数据库;其他的很好,但对于组合框,它将显示数据库中的第一个数据。

这是双击第一个表单的代码:

Private Sub DataGridView1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick

    Dim frmEdit As New Edit

    frmEdit.lblEENo.Text = DataGridView1.CurrentRow.Cells(1).Value.ToString
    frmEdit.txtName.Text = DataGridView1.CurrentRow.Cells(2).Value.ToString
    frmEdit.txtAge.Text = DataGridView1.CurrentRow.Cells(3).Value.ToString
    frmEdit.lblAgeCategory.Text = DataGridView1.CurrentRow.Cells(4).Value.ToString
    frmEdit.txtGender.Text = DataGridView1.CurrentRow.Cells(5).Value.ToString
    frmEdit.cbEthnicity.Text = DataGridView1.CurrentRow.Cells(6).Value.ToString
    frmEdit.cbGrade.Text = DataGridView1.CurrentRow.Cells(7).Value.ToString
    frmEdit.cbCategory.Text = DataGridView1.CurrentRow.Cells(8).Value.ToString
    frmEdit.cbDepartment.Text = DataGridView1.CurrentRow.Cells(9).Value.ToString
    frmEdit.cbPosition.Text = DataGridView1.CurrentRow.Cells(10).Value.ToString
    frmEdit.txtReporting.Text = DataGridView1.CurrentRow.Cells(11).Value.ToString
    frmEdit.DateTimePicker1.Value = DataGridView1.CurrentRow.Cells(12).Value.ToString
    frmEdit.DateTimePicker2.Value = DataGridView1.CurrentRow.Cells(13).Value.ToString

    If DataGridView1.CurrentRow.Cells(14).Value.ToString = "Y" Then
        frmEdit.rbYes.Checked = True
    ElseIf DataGridView1.CurrentRow.Cells(14).Value.ToString = "N" Then
        frmEdit.rbNo.Checked = True
    End If

    frmEdit.cbStatus.Text = DataGridView1.CurrentRow.Cells(15).Value.ToString
    frmEdit.txtNote.Text = DataGridView1.CurrentRow.Cells(16).Value.ToString
    frmEdit.lblMody.Text = tslblLoginAs.Text

    frmEdit.ShowDialog()
    load_data()
End Sub

这是用于连接到组合框的数据库 table 的第二种形式的代码:

Private Sub Edit_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim frmMasterList As New MasterStaff

    Dim poscmd As New SqlCommand("SELECT * from MasterPositionList", conn)
    Dim posadapt As New SqlDataAdapter(poscmd)
    Dim postable As New DataTable
    posadapt.Fill(postable)
    cbPosition.DataSource = postable
    cbPosition.DisplayMember = "PositionName"

    Dim depcmd As New SqlCommand("SELECT * from MasterDepartmentList", conn)
    Dim depadapt As New SqlDataAdapter(depcmd)
    Dim deptable As New DataTable
    depadapt.Fill(deptable)
    cbDepartment.DataSource = deptable
    cbDepartment.DisplayMember = "DeparmentName"
End Sub

我想知道当您可以直接在 DGV 中编辑数据时为什么需要单独的表格。当您想到它时,您尝试编辑的所有数据都已在 DGV 中找到(或者应该存在于其数据源中)。您甚至可以在 DGV 中使用组合框,它们具有自己的绑定数据表。 Here 是一个说明如何完成的示例。

在Edit_Load中没有不必要的重复。您两次加载相同的数据集。您可以重用它,甚至可以在启动时加载它,如果它在应用程序运行时期间没有更改,则可以将其保存在缓存中。

此外,与其从 DGV 中获取值,不如获取选定的 数据行 更好。为此,您只需要记录 ID... 无需访问 UI 属性,而是使用底层数据表。

您不应该使用索引号。如果您想插入列或移动列,请想象一下混乱和潜在的错误。此外,用户可能可以通过拖放对 DGV 中的列重新排序...因此您的逻辑被破坏并且程序将不会像它应该的那样运行。

无论如何,回答你的问题:你已经加载了一个数据表,现在你所要做的就是将它绑定到组合(你已经这样做了)。您已经使用了 DataSource 和 DisplayMember 属性。您可以使用 SelectedValue 在列表中预选一个值,如下所示:

With cbPosition
    .DisplayMember = "PositionName"
    .ValueMember = "PositionName"
    .SelectedValue = "The text value that comes from the DGV"
    .DataSource = postable
End With

只要数据表中存在来自 DGV 的值,这就应该有效。 同样,我认为您应该简化 UI。所有数据都可以在 DGV 中就地编辑。

表单加载事件触发得太晚,无法填充组合框。当您在 DataGridView1_CellDoubleClick() 方法中创建表单实例时,事件几乎立即引发,但事件处理程序实际上 运行 直到控制权返回到消息传递循环,并且没有机会发生在 frmEdit.ShowDialog() 行之前,即 您设置了组合框值之后。因此,加载事件 运行s 在您填充所需值后将覆盖该工作。

要解决此问题,请将 Load 代码移动到构造函数中,就在 InitializeComponent() 方法之后。

此外,由于您想从数据库提供的项目中获取 select,因此您应该使用 SelectedItemSelectedValue 属性,而不是 Text 属性.


最后,在整个应用程序或表单中重复使用相同的连接对象是一种非常糟糕的做法。是的,数据库连接是创建和管理昂贵的对象,但是 ADO.Net 库 已经为您处理了。 您在代码中使用的 SqlConnection 对象是一个在更昂贵的实际原始连接池上的轻量级包装器。当您尝试重用一个 SqlConnection 时,您会在便宜的东西上获得效率,而在更昂贵的东西上失去效率。

相反,每次需要使用数据库时创建(并立即 Dispose()!)一个新的 SqlConnection 对象,并考虑通过减少与数据库的往返次数来减少连接。在这种情况下,您可以将两个 SELECT 语句组合成一个字符串,并在同一个数据库行中填充两个 DataTables:

Private Sub New ' Replaces the current Edit_Load() method
    InitializeComponent()
    Dim results As New DataSet

    'Using block will make sure the connection is closed, **even if an exception is thrown**
    ' Do NOT(!) try to reuse the connection. Only reuse the connection string.
    Using conn As New SqlConnection(connString), _
          ' Two SELECT queries in one string
          cmd As New SqlCommand("SELECT * from MasterPositionList;SELECT * from MasterDepartmentList", conn), _
          da As New DataAdapter(cmd)

                da.Fill(results)
    End Using 'Dispose the database objects as quickly as possible
    cbPosition.DisplayMember = "PositionName"
    cbDepartment.DisplayMember = "DeparmentName"
    cbPosition.DataSource = results.Tables(0) 'Filled two tables in one database call
    cbDepartment.DataSource = results.Tables(1)
End Sub