Rubrik: Controls · TextBox & RichTextBox | VB-Versionen: VB.NET | 06.06.05 |
AutoCompleteTextbox-Control für .NET Dieser .NET-Klassenbibliothek erweitert die Standard-TextBox um eine Autovervollständigungs-Funktion. | ||
Autor: WaldiMaywood | Bewertung: | Views: 17.676 |
ohne Homepage | System: WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 | Beispielprojekt auf CD |
Eine AutoComplete-Funktion in einer TextBox ist schon etwas feines Doch wie lässt sich eine solche Autovervollständigungs-Funktion realisieren? Am liebsten wäre es uns natürlich, man würde ein TextBox-Control auf die Form ziehen ohne für jede TextBox dann eine eigene AutoComplete-Funktion proggen zu müssen. Was liegt also näher, die Standard-TextBox in einer Klassenbibliothek als neues VB.NET Control zu kapseln und diese dann durch entsprechende Eigenschaften und Methoden zu einer AutoComplete-TextBox zu erweitern?
Let's go...
Starten Sie die VS.NET Entwicklungsumgebung und wählen neues "Projekt erstellen". Als Projekt-Typ wählen Sie den Eintrag "Klassenbibliothek" aus und geben als Namen AutoCompleteTextBox ein. Für unser Beispiel benötigen wir außerdem die Klassen aus dem "Windows.Forms" Namespace. Aus diesem Grund müssen wir ein Verweis auf die Dll setzen. Hierzu klicken Sie bitte mit der rechten Maustaste auf den Knoten "Verweise" in ihrer Projektmappe und wählen den Befehl "Verweis hinzufügen". In dem darauf erscheinenden Dialog doppelklicken Sie auf den Eintrag "System.Windows.Forms(.dll)" und klicken anschließend auf OK.
Die vorhandene Datei "Class1.vb" benennen wir am besten um, und zwar in "AutoCompleteTextBox.vb".
Öffnen Sie jetzt diese Datei, löschen den existierenden Code und fügen nachfolgenden neuen Code ein.
Option Explicit On Option Strict On ' // Die benötigten Bibliotheken für unser AutoCompleteTextBox Assembly Imports System.Windows.Forms Imports System.Collections Imports System ' // Der Namespace für unser Assembly Namespace AutoComplete Public Class AutoCompleteTextBox Inherits TextBox ' // Private Variablen Private m_wordList As AutoCompleteWordList Private m_autoComplete As Boolean Private m_insertByEnter As Boolean ' // Standardkonstruktor Public Sub New() MyBase.New() Me.m_wordList = New AutoCompleteWordList ' // WordListArray Instanz erzeugen Me.m_autoComplete = True Me.m_insertByEnter = True End Sub ' // Autocomplete (on/off?) Public Property AutoComplete() As Boolean Get Return Me.m_autoComplete End Get Set(ByVal value As Boolean) Me.m_autoComplete = value End Set End Property ' // Die Wörter automatisch beim drücken der Taste Enter bzw. Return hinzufügen (on/off?) Public Property InsertWordByEnter() As Boolean Get Return Me.m_insertByEnter End Get Set(ByVal value As Boolean) Me.m_insertByEnter = value End Set End Property ' // Das WordListArray Public Property WordList() As AutoCompleteWordList Get Return Me.m_wordList End Get Set(ByVal value As AutoCompleteWordList) Me.m_wordList = value End Set End Property ' // Wort hinzufügen Private Sub InsertWord(ByVal Word As String) ' // Befindet sich das Wort schon in der Liste? If (Me.m_wordList.IndexOf(New AutoComplete.AutoCompleteWord(Word)) = -1) Then ' // Nein. Wort hinzufügen Me.WordList.Add(New AutoComplete.AutoCompleteWord(Me.Text)) End If End Sub ' // Tastatureingaben kontrollieren/checken Private Function CheckKeys(ByVal e As KeyEventArgs) As Boolean If (Not Me.m_autoComplete OrElse _ Me.Text.Length < 1 OrElse _ e.KeyCode = Keys.Back OrElse _ e.KeyCode = Keys.Tab OrElse _ e.KeyCode = Keys.Delete) Then Return False ' // Return. Keine Aktion mehr durchführen ElseIf (m_insertByEnter AndAlso _ (e.KeyCode = Keys.Enter OrElse e.KeyCode = Keys.Return)) Then ' // Wort hinzufügen, da Enter bzw. Return gedrückt wurde Me.InsertWord(Me.Text) End If Return True End Function ' // Das eingegebene Wort vervollständigen Private Sub DoAutoCompleteText(ByVal e As KeyEventArgs) Static TextOld As String Dim pos, idx As Integer With Me If (TextOld Is Nothing OrElse Not .Text.Equals(TextOld)) Then idx = Me.WordList.IndexOf(New AutoComplete.AutoCompleteWord(.Text)) ' // Befindet sich das eigegebene Wort in unserem Array? ' // Hierfür wird keine "einfache" Schleife verwendet, sondern es wurde ein ' // eigene Word Klasse angelegt, in welcher die Equals() Methode überschrieben wurde. ' // Auf diese Methode greift wiederrum die ArrayList.IndexOf() Funktion zu. ' // Wir können sozusagen die Suche (bzw. das Verhalten der IndexOf() Methode) von der ArrayListKlasse ändern/steuern. If (idx > -1) Then ' // Ja, das Wort befindet sich in unseren WordListArray TextOld = .Text pos = .SelectionStart .Text = .Text + Me.WordList(idx).Word.Substring(.Text.Length) .SelectionStart = pos .SelectionLength = .Text.Length - (.SelectionStart) ' // SelectionStart/End usw. setzen Return End If End If End With End Sub Private Sub TextBox_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) _ Handles MyBase.KeyUp ' // Es wurde eine Taste in der TextBox gedrückt If (Not Me.CheckKeys(e)) Then Return Me.DoAutoCompleteText(e) End Sub End Class ' // Unsere etwas modifizierte ArrayList-Klasse Public Class AutoCompleteWordList Inherits ArrayList ' // Wort hinzufügen #1 (Value = WordObjekt) Public Overloads Function Add(ByVal value As AutoCompleteWord) As Integer MyBase.Add(value) End Function ' // Wort hinzufügen #2 (Value = String) Public Overloads Function Add(ByVal value As String) As Integer MyBase.Add(New AutoComplete.AutoCompleteWord(value)) End Function ' // Auf die Items (Wörter) zugreifen Default Public Shadows Property Item(ByVal index As Integer) As AutoCompleteWord Get Return CType(MyBase.Item(index), AutoComplete.AutoCompleteWord) End Get Set(ByVal Value As AutoCompleteWord) MyBase.Item(index) = Value End Set End Property ' // Die überschriebene Methode IndexOf() Public Shadows Function IndexOf(ByVal value As Object) As Integer ' // Ist Value ein String, müssen wir daraus ein AutoCompleteWord-Objekt erzeugen If value.GetType() Is GetType(String) Then Return MyBase.IndexOf(New AutoComplete.AutoCompleteWord(value.ToString())) Else ' // Value ist in diesen Fall schon ein AutoCompleteWord-Objekt, ' // kann demnach direkt übergeben werden Return MyBase.IndexOf(value) End If End Function End Class ' // Klasse AutoCompleteWord Public Class AutoCompleteWord ' // Private Variable Private m_Word As String ' // Konstruktor, mit Übergabe eines Wortes Public Sub New(ByVal Word As String) Me.m_Word = Word End Sub ' // Die überschreibene Methode Equals, auf welche wiederrum die IndexOf() ' // Methode zurückgreift (wie oben beschrieben) Public Overloads Overrides Function Equals(ByVal word As Object) As Boolean Return (CType(word, AutoCompleteWord).Word.StartsWith(Me.Word)) End Function ' // Das Wort zurückgeben Public Property Word() As String Get Return Me.m_Word End Get Set(ByVal Value As String) Me.m_Word = Value End Set End Property End Class End Namespace
Jetzt können Sie den Code/das Projekt kompilieren. Drücken Sie hierfür bitte die Taste F5. Normalerweise sollte alles klappen, und die IDE einen Hinweis darüber ausgeben, dass eine Klassenbibliothek nicht direkt gestartet werden kann. Das ist auch richtig.
Nun wollen wir natürlich auch dieses Assembly/Control benutzen bzw. testen.
- Klicken Sie dazu mit der rechten Maustaste auf ihre vorhandene Projektmappe (nicht das Projekt an sich und bitte kein neues VS Instanz starten)
- Hinzufügen -> Neues Projekt -> Visual Basic -> Windowsanwendung -> Namen eingeben, bspw.: "AutoCompleteTextBoxTestApp"
- Öffnen Sie die Form1.vb im Designer
- Jetzt klicken Sie mit der rechten Maustaste auf die Toolbar im Tab "Eigene Controls"
- Element hinzufügen -> Durchsuchen -> In den Ordner wechseln in welcher sich das Projekt "AutoCompleteTextBox" befindet
- Das Assembly befindet sich normalerweise im Ordner ".\AutoCompleteTextBox\bin"
- Bitte wählen Sie die Datei "AutoCompleteTextBox.dll" aus und klicken Sie anschliessend auf Ok.
- Jetzt sollte/müsste sich in der Toolbar ein neuer Eintrag befinden. Unsere eigene TextBox.
- Dieses Control können Sie jetzt wie üblich auf die Form ziehen
- Zusätzlich benötigen wir für dieses Bsp. 3 Buttons und 2 Checkboxen
- Danach fügen Sie bitte diesen Code ein: (Die Designerregion auf keinen Fall löschen!)
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Vom Windows Form Designer generierter Code " #End Region Private Sub Button2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button2.Click Me.AutoCompleteTextBox1.WordList.Clear() End Sub Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' // Test-Eintrag für die AutoComplete-Liste Me.AutoCompleteTextBox1.WordList.Add("vbarchiv ist spitze") Me.AutoCompleteTextBox1.Text = String.Empty Me.Button1.Text = "Wort hinzufügen" Me.Button2.Text = "Wortliste leeren" Me.Button3.Text = "Wortliste anzeigen" Me.CheckBox1.Text = "Autocomplete" Me.CheckBox2.Text = "Insert word by enter" Me.CheckBox1.Checked = True Me.CheckBox2.Checked = True End Sub Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged Me.AutoCompleteTextBox1.AutoComplete = Me.CheckBox1.Checked End Sub Private Sub CheckBox2_CheckedChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles CheckBox2.CheckedChanged Me.AutoCompleteTextBox1.InsertWordByEnter = Me.CheckBox2.Checked End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click If Me.AutoCompleteTextBox1.WordList.IndexOf(Me.AutoCompleteTextBox1.Text) = -1 Then Me.AutoCompleteTextBox1.WordList.Add(Me.AutoCompleteTextBox1.Text) End If End Sub Private Sub Button3_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button3.Click Dim f As New Form Dim l As New ListBox l.DataSource = Me.AutoCompleteTextBox1.WordList l.DisplayMember = "Word" l.Dock = DockStyle.Fill f.Controls.Add(l) f.ShowDialog() End Sub End Class
Ist dies getan, wollen wir das Control natürlich ausprobieren. Klicken Sie hierzu bitte mit der rechten Maustaste auf das "AutoCompleteTextBoxTestApp Projekt" und danach auf den Eintrag "Als Startobjekt festlegen". Jetzt kann das Programm mit F5 kompiliert und gestartet werden. Nach dem Start einfach einmal "vb" in der TextBox eingeben und siehe da, der Satz wurde vervollständig )