You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.Net中限制DataGridView自动完成文本框仅选建议项及联动Unit列

VB.Net DataGridView 产品名称列强制选择与自动填充单位实现方案

需求概述

  • 强制DataGridView的ProductName列仅允许选择自动完成建议列表内的条目
  • 输入合法产品名称时,自动从数据库加载对应Unit列的数据
  • 若用户通过退格、ESC等操作输入列表外内容,弹出提示并限制离开该列直至输入合法

修改后完整代码

Form1 代码

Imports System.Data.OleDb
Imports Dapper

Public Class Form1
    Dim ProductsService As New ProductsService()
    Private validProductNames As List(Of String) ' 存储合法产品名称列表
    Private productsList As List(Of Products) ' 存储所有产品数据,用于匹配Unit

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' 预加载所有产品数据,避免重复查询数据库
        productsList = ProductsService.GetAllProducts().ToList()
        validProductNames = productsList.Select(Function(p) p.ProductName).Distinct().ToList()
    End Sub

    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
        Dim column As Integer = DataGridView1.CurrentCell.ColumnIndex
        Dim headerText As String = DataGridView1.Columns(column).HeaderText

        If headerText.Equals("ProductName") Then
            Dim tb As TextBox = TryCast(e.Control, TextBox)

            If tb IsNot Nothing Then
                ' 移除旧的事件绑定,避免重复触发
                RemoveHandler tb.KeyDown, AddressOf ProductNameTextBox_KeyDown
                
                tb.AutoCompleteMode = AutoCompleteMode.SuggestAppend ' 建议+自动补全,提升用户体验
                tb.AutoCompleteSource = AutoCompleteSource.CustomSource
                tb.AutoCompleteCustomSource.Clear()
                tb.AutoCompleteCustomSource.AddRange(validProductNames.ToArray())

                ' 添加按键监听事件
                AddHandler tb.KeyDown, AddressOf ProductNameTextBox_KeyDown
            End If
        Else
            Dim tb As TextBox = TryCast(e.Control, TextBox)
            If tb IsNot Nothing Then
                tb.AutoCompleteMode = AutoCompleteMode.None
            End If
        End If
    End Sub

    ' 验证ProductName列输入合法性
    Private Sub DataGridView1_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
        If DataGridView1.Columns(e.ColumnIndex).HeaderText.Equals("ProductName") Then
            Dim inputText As String = e.FormattedValue.ToString().Trim()

            ' 检查输入是否在合法列表中(忽略大小写)
            If Not validProductNames.Contains(inputText, StringComparison.OrdinalIgnoreCase) Then
                e.Cancel = True ' 取消单元格编辑,阻止离开
                MessageBox.Show("请选择建议列表中的产品名称,输入内容不合法!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
                ' 保持当前单元格处于编辑状态
                DataGridView1.CurrentCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
            Else
                ' 自动填充Unit列(匹配第一个符合的产品Unit,可根据需求调整)
                Dim targetProduct = productsList.FirstOrDefault(Function(p) p.ProductName.Equals(inputText, StringComparison.OrdinalIgnoreCase))
                If targetProduct IsNot Nothing Then
                    DataGridView1.Rows(e.RowIndex).Cells("Unit").Value = targetProduct.Unit
                End If
            End If
        End If
    End Sub

    ' 处理ProductName文本框的按键事件
    Private Sub ProductNameTextBox_KeyDown(sender As Object, e As KeyEventArgs)
        Dim tb As TextBox = DirectCast(sender, TextBox)
        ' 处理ESC键:若输入非法则清空内容并提示
        If e.KeyCode = Keys.Escape Then
            If Not validProductNames.Contains(tb.Text.Trim(), StringComparison.OrdinalIgnoreCase) Then
                tb.Text = String.Empty
                MessageBox.Show("请选择建议列表中的产品名称,输入内容不合法!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
                e.Handled = True ' 阻止默认ESC行为
            End If
        End If
    End Sub
End Class

Products 实体类

Public Class Products
    Public Property Id() As Integer
    Public Property ProductName() As String
    Public Property Unit() As String
End Class

ProductsService 数据访问类

Imports System.Data.OleDb
Imports Dapper

Public Class ProductsService
    Public Function GetOledbConnectionString() As String
        Return "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\test03092024.accdb;Persist Security Info=False;"
    End Function

    ' 获取所有产品完整数据(含Id、ProductName、Unit)
    Public Function GetAllProducts() As IEnumerable(Of Products)
        Dim sql = "SELECT Id, ProductName, Unit FROM [Products]"
        Using _conn = New OleDbConnection(GetOledbConnectionString())
            Return _conn.Query(Of Products)(sql).ToList()
        End Using
    End Function
End Class

关键实现说明

  • 预加载数据:在窗体加载时一次性获取所有产品数据,存储到内存列表中,避免每次编辑单元格时重复查询数据库,提升响应速度。
  • 输入验证拦截:通过CellValidating事件拦截单元格编辑结束操作,若输入不在合法列表中则取消验证,强制用户留在当前单元格重新输入。
  • 自动填充逻辑:输入验证通过后,直接从内存列表中匹配对应产品的Unit值,填充到同行的Unit列,无需再次查询数据库。
  • 特殊按键处理:监听文本框的ESC按键,若当前输入非法则清空内容并提示,防止用户通过ESC跳过验证。
  • 自动完成优化:将自动完成模式设为SuggestAppend,既显示建议列表又自动补全匹配文本,提升用户输入效率;同时每次编辑前清空并重新绑定数据源,避免数据冗余。

内容的提问来源于stack exchange,提问作者dlaksmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:37:04