我正在尝试使用文本框事件 TextChanged 自动完成,但使用 VB.NET 运行速度很慢。
虽然只有6条记录,但我的代码有问题吗,请指导我。
我附上了一个示例文件的 gif,当我输入“KBE”时,它运行得非常慢,并提出了一些建议,直到它自行完成,然后我尝试输入“KBT”,它也运行得非常慢 并提出一些建议,直到它自行完成
谢谢
Public Class Form3
Private iService As New ItemService()
Private bindingSource1 As BindingSource = Nothing
Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblcodeproduct.Visible = False
TextBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend
TextBox1.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox1.AutoCompleteCustomSource.AddRange(iService.GetByCodeProduct().Select(Function(n) n.CodeProduct).ToArray())
End Sub
Private Sub GetItemData2(ByVal iditem As String)
Dim item = iService.GetByCodeProductOrBarcode(iditem)
If item IsNot Nothing Then
If String.Equals(iditem, item.CodeProduct, StringComparison.CurrentCultureIgnoreCase) Then
TextBox1.Text = item.CodeProduct
End If
TextBox2.Text = item.Barcode
Else
TextBox2.Clear()
Return
End If
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.Text = "" Then
lblcodeproduct.Visible = False
ErrorProvider1.SetError(TextBox1, "")
Else
bindingSource1 = New BindingSource With {.DataSource = New BindingList(Of Stock)(CType(iService.GetByCodeProductlike(TextBox1.Text), IList(Of Stock)))}
If bindingSource1.Count > 0 Then
lblcodeproduct.Visible = False
ErrorProvider1.SetError(TextBox1, "")
Else
lblcodeproduct.Visible = True
End If
GetItemData2(TextBox1.Text)
End If
End Sub
End Class
Public Class Stock
Public Property Id() As Integer
Public Property CodeProduct() As String
Public Property Barcode() As String
End Class
Public Class ItemService
Public Function GetOledbConnectionString() As String
Return "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TRIAL.accdb;Persist Security Info=False;"
End Function
Private ReadOnly _conn As OleDbConnection
Private _connectionString As String = GetOledbConnectionString()
Public Sub New()
_conn = New OleDbConnection(_connectionString)
End Sub
Public Function GetByCodeProduct() As IEnumerable(Of Stock)
Dim sql = "SELECT CodeProduct AS CodeProduct FROM Items"
Using _conn = New OleDbConnection(GetOledbConnectionString())
Return _conn.Query(Of Stock)(sql).ToList()
End Using
End Function
Public Function GetByCodeProductlike(ByVal CodeProduct As String) As IEnumerable(Of Stock)
Dim sql = $"SELECT CodeProduct FROM Items WHERE CodeProduct LIKE '%" & CodeProduct & "%'"
Using _conn = New OleDbConnection(GetOledbConnectionString())
Return _conn.Query(Of Stock)(sql).ToList()
End Using
End Function
Public Function GetByCodeProductOrBarcode(ByVal code As String) As Stock
Dim sql = $"SELECT * FROM Items WHERE CodeProduct = '{code}' or Barcode = '{code}'"
Using _conn = New OleDbConnection(GetOledbConnectionString())
Return _conn.Query(Of Stock)(sql).FirstOrDefault()
End Using
End Function
End Class
结果自动完成文本框
您对 TextChanged 事件进行了递归调用,因为 GetItemData2 可能会更改 TextBox1。我已用“<<<<<<<<<<<<<<<<<<<<<<<<<.
”标记了所做的更改Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Static recursive As Boolean = False '<<<<<<<<<<<<<<<<<<<<<<<<<
If recursive Then Exit Sub '<<<<<<<<<<<<<<<<<<<<<<<<<
recursive = True '<<<<<<<<<<<<<<<<<<<<<<<<<
If TextBox1.Text = "" Then
lblcodeproduct.Visible = False
ErrorProvider1.SetError(TextBox1, "")
Else
bindingSource1 = New BindingSource With {.DataSource = New BindingList(Of Stock)(CType(iService.GetByCodeProductlike(TextBox1.Text), IList(Of Stock)))}
If bindingSource1.Count > 0 Then
lblcodeproduct.Visible = False
ErrorProvider1.SetError(TextBox1, "")
Else
lblcodeproduct.Visible = True
End If
' the following method might change TextBox1
' which results in the .TextChanged event being called again
' the changes mean that second call stops the processing of the .TextChanged event
GetItemData2(TextBox1.Text)
End If
recursive = False '<<<<<<<<<<<<<<<<<<<<<<<<<
End Sub