当用户在 vb.net 中按多个键时,如何在文本框中处理

how to handle in textbox when the user presses multiple keys in vb.net

提问人:siwa86 提问时间:10/4/2023 最后编辑:siwa86 更新时间:10/6/2023 访问量:121

问:

当用户在 vb.net 中按多个键时,如何在文本框中处理。

当用户按键盘键 backspace 和 esc 而不回车时,存在用户可以在列表之外选择的问题。请指导我。 这是修改建议和准则后的以下代码 @dr.null

谢谢


 
Imports System.Data.OleDb

Public Class Form7
Private connectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\dapperdemo.accdb;Persist Security Info=False;"
    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
 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 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 TextBox1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
        Dim product = TextBox1.Text.Trim()
        Dim products = TextBox1.AutoCompleteCustomSource.Cast(Of String)

        'If product.Length > 0 AndAlso products.Any() AndAlso
        If 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
  Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
        If e.KeyCode = Keys.Enter Then
            Me.ValidateChildren()
        End If
    End Sub
End Class

Screenshot Form7

vb.net WinForms 自动完成 文本框

评论

0赞 nbk 10/4/2023
为什么有一个文本框,您可以在解析它之前删除所有非 ASCII 字符。但基本上更简单的方法是使用下拉菜单并检查是否选择了索引
0赞 jmcilhinney 10/4/2023
我在那里没有看到任何与按键相关的代码,那么实际问题是什么?请提供完整而清晰的问题解释。
0赞 dr.null 10/4/2023
忘记这个键的东西,在你的save/add/insert/ok/what按钮点击事件处理程序中,首先调用这个。这样可以防止在任何验证失败时插入/更新记录。If Not Me.ValidateChildren() Then Return
0赞 siwa86 10/4/2023
@nbk,你的意思是组合框
1赞 djv 10/5/2023
@jmcilhinney 哦,我马上就想起了之前的帖子,当我在这里看到第一条评论时,...basically simpler it would be to use a Pull-Down

答:

0赞 djv 10/6/2023 #1

此答案将涉及 .尝试一下,看看感觉是否正常。您将看到,当 设置为 时,它甚至不允许用户选择不在列表中的项目。这似乎是您正在寻找的行为,因为太宽容了。ComboBoxDropDownStyleComboBoxStyle.DropDownListTextBox

我将把你的数据库查询移出UI。查询可能很快,但在这两种情况下,我都不会在 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

没有理由返回 .你只需要一个字符串的枚举,所以它就在那里。如果您不关心定义两者,则非异步函数可以作为 lambda 包含在异步函数中。DataTable

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 方法)现在被标记为 ,并且我们是从数据库返回数据的任务的结果。AsyncAwait

在控件上填充并设置一些与“自动完成”相关的属性。另请注意,控件不需要进行任何验证或进行其他验证。此代码的行为将与当前版本完全相同,带有 TextBox,并且没有我刚才提到的其他代码。ComboBox.ItemsWndProc

如果将 更改为 ,则不允许用户选择列表中的项以外的任何内容。验证是内置的。你可能不喜欢这种感觉。DropDownStyleDropDownList

ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList

使用样式,可以执行验证以强制用户在列表中输入内容。这具有您想要的自动完成功能。但是,它非常严格,并且不允许用户离开,直到他在列表中选择某些内容DropDownComboBox

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

评论

0赞 dr.null 10/6/2023
DT的。AcceptChanges() '这真的有必要吗? 是的。当您填充它时,以及当您更新数据库时。否则,行会保留错误的状态,您将无法从有用的方法中受益,例如 、 、 、 ...等。有用的属性,如 、 、 ...等。RejectChangesGetChangesSelectDataView.RowStateFilterDataView.RowFilter
2赞 jmcilhinney 10/6/2023
@dr.null,实际上,该显式调用不是必需的。您说得对,有必要调用,但默认情况下已经在内部调用了。默认情况下,所有数据适配器都继承属性,并且两者都继承。例如,如果要从一个数据库中检索记录并将其插入到另一个数据库中,则可以将前者设置为何处。例如,如果要将更改插入到两个数据库表中,则可以将后者设置为何处。AcceptChangesFillUpdateAcceptChangesDuringFillAcceptChangesDuringUpdateTrueFalseFalse
0赞 siwa86 10/6/2023
@djv,谢谢你的回答,我在输入时尝试了你的代码,然后出现了自动完成,然后我从列表中选择,然后我使用了键盘退格键和esc,结果在列表之外,但消息框没有出来,如果我关闭表单,消息框就会出现
0赞 dr.null 10/6/2023
@jmcilhinney同意。但是,如果不使用适配器,则需要显式设置。
0赞 siwa86 10/6/2023
@djv,谢谢你的回答,我在输入时尝试了你的代码,然后出现了自动完成,然后我从列表中选择,然后我使用了键盘退格键和esc,结果在列表之外,但消息框没有出来,如果我关闭表单,消息框就会出现