在 vb.net 中,当用户按下多个按键时,如何在文本框中进行处理。
当用户按下键盘上的退格键和退出键而不输入时,会出现用户可以选择列表之外的问题。请指导我。
谢谢
Private connectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\demo.accdb;Persist Security Info=False;"
Private Function GetData() As DataTable
Dim conString As String = connectionString
Dim query As String = "SELECT CODEPRODUCT FROM Items"
Dim dt As New DataTable()
Using con As OleDbConnection = New OleDbConnection(conString),
cmd As OleDbCommand = New OleDbCommand(query, con),
sda As OleDbDataAdapter = New OleDbDataAdapter(cmd)
sda.Fill(dt)
End Using
dt.AcceptChanges()
Return dt
End Function
Private Sub Form7_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim acsCustomers As New AutoCompleteStringCollection
Using dt As DataTable = GetData()
acsCustomers.AddRange(
dt.AsEnumerable().
Select(Function(r) r.Field(Of String)("CODEPRODUCT")).ToArray())
End Using
TextBox1.AutoCompleteMode = AutoCompleteMode.Suggest
TextBox1.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox1.AutoCompleteCustomSource = acsCustomers
AutoValidate = AutoValidate.EnableAllowFocusChange
End Sub
Private Sub TextBox1_Validating(sender As Object, e As CancelEventArgs) Handles TextBox1.Validating
Dim product = TextBox1.Text.Trim()
Dim products = TextBox1.AutoCompleteCustomSource.Cast(Of String)
If product.Length > 0 AndAlso products.Any() AndAlso
Not products.Contains(product, StringComparer.OrdinalIgnoreCase) Then
MessageBox.Show("Please Select From List Only...")
e.Cancel = True
TextBox1.SelectAll()
' Or
' TextBox1.Clear()
End If
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = &H10 Then
Dim av = Me.AutoValidate
Me.AutoValidate = AutoValidate.Disable
MyBase.WndProc(m)
Me.AutoValidate = av
Return
End If
MyBase.WndProc(m)
End Sub
这个答案将涉及
ComboBox
。尝试一下,看看感觉是否可以。您会发现,当 DropDownStyle
设置为 ComboBoxStyle.DropDownList
时,用户甚至无法选择不在列表中的项目。这似乎是您正在寻找的行为,因为 TextBox
太宽松了。
我将把您的数据库查询移出用户界面。查询可能很快,但在任何一种情况下,我都不会在 UI 上通过数据库查询提供答案。如果查询很慢,您会注意到 UI 性能有所改善。
Private Function GetCodeProducts() As IEnumerable(Of String)
Dim result As String()
Using dt As New DataTable(),
con As New OleDbConnection(connectionString),
cmd As New OleDbCommand("SELECT CODEPRODUCT FROM Items", con),
sda As New OleDbDataAdapter(cmd)
sda.Fill(dt)
dt.AcceptChanges() ' is this really necessary?
result = dt.AsEnumerable().Select(Function(r) r.Field(Of String)("CODEPRODUCT")).ToArray()
End Using
Return result
End Function
Private Function GetCodeProductsAsync() As Task(Of IEnumerable(Of String))
Return Task.Run(AddressOf GetCodeProducts)
End Function
没有理由退货
DataTable
。您只需要一个可枚举的字符串即可。如果您不关心定义两者,那么非异步函数可以作为 lambda 包含在异步函数内。
Private Async Sub Form7_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim codeProducts = Await GetCodeProductsAsync()
ComboBox1.Items.AddRange(codeProducts.ToArray())
ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
ComboBox1.AutoCompleteSource = AutoCompleteSource.ListItems
ComboBox1.DropDownStyle = ComboBoxStyle.DropDown
End Sub
请注意,Form_Load(一种 UI 方法)现在标记为
Async
,我们 Await
从数据库返回数据的任务结果。
填充
ComboBox.Items
并在控件上设置一些与自动完成相关的属性。另请注意,该控件不需要 WndProc
或其他验证。 此代码的行为与您当前的版本完全相同,带有 TextBox
,并且没有我刚才提到的附加代码。
如果将
DropDownStyle
更改为 DropDownList
,则用户将无法选择列表中项目以外的任何内容。验证是内置的。您可能不喜欢这种感觉。
ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
使用
DropDown
样式,您可以执行验证以强制用户在列表中输入某些内容。这可以根据您的需要自动完成。然而,它的限制性很大,不允许用户离开 ComboBox
,直到他在列表中选择某些内容
Private Sub ComboBox1_Validating(sender As Object, e As CancelEventArgs) Handles ComboBox1.Validating
If Not ComboBox1.Items.Contains(ComboBox1.Text.Trim()) Then
MessageBox.Show("Please Select From List Only...")
e.Cancel = True
End If
End Sub