我在网上到处寻找解决这种常见疼痛的方法。当然有人在那里有一个解决方案或者可以帮我实现一个????
基本上vb.net中的默认组合框使用有限的“StartsWith”模式匹配自动填充(例如,当您键入任何字母时,只有以该字母开头的listitems.text将被过滤并显示在下拉列表中。< / p>
有一个明显简单的开关来改变这些被过滤的方式,所以我认为解决这个问题的最好方法是派生/继承组合框并修改它以使用String.contains()??唯一的问题我从来没有做过派生类,并且非常感谢对这个特定问题的一些帮助。
此外,我发现了一个C#解决方案似乎正好解决了这个问题(http://www.codeproject.com/Tips/631196/ComboBox-with-Suggest-Ability-based-on-Substring-S),并且我已经尝试了所有转换或代码类似的东西但收效甚微:(
我很惊讶这仍然没有解决,因为网上有这么多人要求解决这个限制!!!!
答案 0 :(得分:1)
是的,可以在VB.NET中完成。我正在进行相同的思考过程,您可以尝试将您从C#发布的链接中的代码转换为VB.NET,如前面的评论建议的那样。但是,当我尝试这样做时,生成的VB将无法编译。在修复了许多构建错误和一些语法错误之后,我向您展示了SuggestComboBox
的VB版本及其使用方法。我发布这个答案的唯一原因是因为从C#到VB的转换并不简单,而且发布源的许可允许我这样做。
你需要通过表单后面的代码添加控件,我在源代码中找不到设计器部分(归咎于我对C#缺乏了解)。
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Windows.Forms
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim testbox As New AutoCompleteComboBox.SuggestComboBox
Me.Controls.Add(testbox)
testbox.DataSource = New List(Of String) From {"Janean Mcgaha", "Tama Gaitan", "Jacque Tinnin", "Elvira Woolfolk", "Fransisca Owens", "Minnie Ardoin", _
"Renay Bentler", "Joye Boyter", "Jaime Flannery", "Maryland Arai", "Walton Edelstein", "Nereida Storrs", _
"Theron Zinn", "Katharyn Estrella", "Alline Dubin", "Edra Bhatti", "Willa Jeppson", "Chelsea Revel", _
"Sonya Lowy", "Danelle Kapoor"}
End Sub
End Class
Namespace AutoCompleteComboBox
Public Class SuggestComboBox
Inherits ComboBox
#Region "fields and properties"
Private ReadOnly _suggLb As New ListBox() With {.Visible = False, .TabStop = False}
Private ReadOnly _suggBindingList As New BindingList(Of String)()
Private _propertySelector As Expression(Of Func(Of ObjectCollection, IEnumerable(Of String)))
Private _propertySelectorCompiled As Func(Of ObjectCollection, IEnumerable(Of String))
Private _filterRule As Expression(Of Func(Of String, String, Boolean))
Private _filterRuleCompiled As Func(Of String, Boolean)
Private _suggestListOrderRule As Expression(Of Func(Of String, String))
Private _suggestListOrderRuleCompiled As Func(Of String, String)
Public Property SuggestBoxHeight() As Integer
Get
Return _suggLb.Height
End Get
Set(value As Integer)
If value > 0 Then
_suggLb.Height = value
End If
End Set
End Property
''' <summary>
''' If the item-type of the ComboBox is not string,
''' you can set here which property should be used
''' </summary>
Public Property PropertySelector() As Expression(Of Func(Of ObjectCollection, IEnumerable(Of String)))
Get
Return _propertySelector
End Get
Set(value As Expression(Of Func(Of ObjectCollection, IEnumerable(Of String))))
If value Is Nothing Then
Return
End If
_propertySelector = value
_propertySelectorCompiled = value.Compile()
End Set
End Property
'''<summary>
''' Lambda-Expression to determine the suggested items
''' (as Expression here because simple lamda (func) is not serializable)
''' <para>default: case-insensitive contains search</para>
''' <para>1st string: list item</para>
''' <para>2nd string: typed text</para>
'''</summary>
Public Property FilterRule() As Expression(Of Func(Of String, String, Boolean))
Get
Return _filterRule
End Get
Set(value As Expression(Of Func(Of String, String, Boolean)))
If value Is Nothing Then
Return
End If
_filterRule = value
_filterRuleCompiled = Function(item) value.Compile()(item, Text)
End Set
End Property
'''<summary>
''' Lambda-Expression to order the suggested items
''' (as Expression here because simple lamda (func) is not serializable)
''' <para>default: alphabetic ordering</para>
'''</summary>
Public Property SuggestListOrderRule() As Expression(Of Func(Of String, String))
Get
Return _suggestListOrderRule
End Get
Set(value As Expression(Of Func(Of String, String)))
If value Is Nothing Then
Return
End If
_suggestListOrderRule = value
_suggestListOrderRuleCompiled = value.Compile()
End Set
End Property
#End Region
''' <summary>
''' ctor
''' </summary>
Public Sub New()
' set the standard rules:
_filterRuleCompiled = Function(s) s.ToLower().Contains(Text.Trim().ToLower())
_suggestListOrderRuleCompiled = Function(s) s
_propertySelectorCompiled = Function(collection) collection.Cast(Of String)()
_suggLb.DataSource = _suggBindingList
AddHandler _suggLb.Click, AddressOf SuggLbOnClick
AddHandler ParentChanged, AddressOf OnParentChanged
End Sub
''' <summary>
''' the magic happens here ;-)
''' </summary>
''' <param name="e"></param>
Protected Overrides Sub OnTextChanged(e As EventArgs)
MyBase.OnTextChanged(e)
If Not Focused Then
Return
End If
_suggBindingList.Clear()
_suggBindingList.RaiseListChangedEvents = False
_propertySelectorCompiled(Items).Where(_filterRuleCompiled).OrderBy(_suggestListOrderRuleCompiled).ToList().ForEach(AddressOf _suggBindingList.Add)
_suggBindingList.RaiseListChangedEvents = True
_suggBindingList.ResetBindings()
_suggLb.Visible = _suggBindingList.Any()
If _suggBindingList.Count = 1 AndAlso _suggBindingList.[Single]().Length = Text.Trim().Length Then
Text = _suggBindingList.[Single]()
[Select](0, Text.Length)
_suggLb.Visible = False
End If
End Sub
#Region "size and position of suggest box"
''' <summary>
''' suggest-ListBox is added to parent control
''' (in ctor parent isn't already assigned)
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Overloads Sub OnParentChanged(sender As Object, e As EventArgs)
Parent.Controls.Add(_suggLb)
Parent.Controls.SetChildIndex(_suggLb, 0)
_suggLb.Top = Top + Height - 3
_suggLb.Left = Left + 3
_suggLb.Width = Width - 20
_suggLb.Font = New Font("Segoe UI", 9)
End Sub
Protected Overrides Sub OnLocationChanged(e As EventArgs)
MyBase.OnLocationChanged(e)
_suggLb.Top = Top + Height - 3
_suggLb.Left = Left + 3
End Sub
Protected Overrides Sub OnSizeChanged(e As EventArgs)
MyBase.OnSizeChanged(e)
_suggLb.Width = Width - 20
End Sub
#End Region
#Region "visibility of suggest box"
Protected Overrides Sub OnLostFocus(e As EventArgs)
' _suggLb can only getting focused by clicking (because TabStop is off)
' --> click-eventhandler 'SuggLbOnClick' is called
If Not _suggLb.Focused Then
HideSuggBox()
End If
MyBase.OnLostFocus(e)
End Sub
Private Sub SuggLbOnClick(sender As Object, eventArgs As EventArgs)
Text = _suggLb.Text
Focus()
End Sub
Private Sub HideSuggBox()
_suggLb.Visible = False
End Sub
Protected Overrides Sub OnDropDown(e As EventArgs)
HideSuggBox()
MyBase.OnDropDown(e)
End Sub
#End Region
#Region "keystroke events"
''' <summary>
''' if the suggest-ListBox is visible some keystrokes
''' should behave in a custom way
''' </summary>
''' <param name="e"></param>
Protected Overrides Sub OnPreviewKeyDown(e As PreviewKeyDownEventArgs)
If Not _suggLb.Visible Then
MyBase.OnPreviewKeyDown(e)
Return
End If
Select Case e.KeyCode
Case Keys.Down
If _suggLb.SelectedIndex < _suggBindingList.Count - 1 Then
_suggLb.SelectedIndex += 1
End If
Return
Case Keys.Up
If _suggLb.SelectedIndex > 0 Then
_suggLb.SelectedIndex -= 1
End If
Return
Case Keys.Enter
Text = _suggLb.Text
[Select](0, Text.Length)
_suggLb.Visible = False
Return
Case Keys.Escape
HideSuggBox()
Return
End Select
MyBase.OnPreviewKeyDown(e)
End Sub
Private Shared ReadOnly KeysToHandle As List(Of Keys) = New List(Of Keys) From {Keys.Down, Keys.Up, Keys.Enter, Keys.Escape}
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
' the keysstrokes of our interest should not be processed be base class:
If _suggLb.Visible AndAlso KeysToHandle.Contains(keyData) Then
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
#End Region
End Class
End Namespace