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
相关产品推荐
相关产品推荐

