Tuesday, May 5, 2009

Auto Complete Textbox for Vb.Net Desktop Applications

Hi all,

Ever tried the google toolbar? Whenever you type something, the results are displayed related to the type text just below the textbox. Have you ever wondered if you can include the same thing in your project.


Edited on < 10 AM EST, 19th May 2009: >
Click here for the complete project


I tried to achieve the following :

If I enter a file name, then all the file names which has the text entered by me should appear in a pop up just below my textbox. If somebody cannot access the code at the codeplex, or if somebody cannot download, I have added the code right here :

I applied the following trick :

I loaded few paths to a collection. Created a textbox, and a combobox just behind the textbox so that it should not be visible, but its drop down should be. If I enter some name, and if the text is present in the combobbox items, then the combobox dropdown should display all the items which has that text. Ofcourse, the items should be grouped accordingly.

First step, add a class "AutoCompleteEntry". This will be the class which will be bound to the collection as Combobox Items.





Imports System.IO

Public Class AutoCompleteEntry
Public type As String

Public information As FileInfo

Public Sub New(ByVal type As String, ByVal fileInformation As FileInfo)
Me.type = type
information = fileInformation
End Sub

Public Property FileType() As String
Get
Return type
End Get
Set(ByVal value As String)
type = value
End Set
End Property

Public Property FileInformation() As FileInfo
Get
Return information
End Get
Set(ByVal value As FileInfo)
information = value
End Set
End Property

Public ReadOnly Property ParentFolder() As String
Get
Return information.Name
End Get
End Property

Public ReadOnly Property Name() As String
Get
Return information.Name
End Get
End Property

Public ReadOnly Property Size() As String
Get
Return information.Length & " bytes"
End Get
End Property

End Class



2nd Step, create a Xaml File with the Name of SearchControl.Xaml and add the following code there.



< UserControl x:Class="SearchControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
< UserControl.Resources>
< DataTemplate x:Key="cmbTemplate">
< StackPanel Orientation="Horizontal" Width="250">
< TextBlock Text="{Binding Path=Name}" Width="100" />
< TextBlock Text="{Binding Path=ParentFolder}" Width="70" HorizontalAlignment="Left" Margin="5,0,0,0"/>
< TextBlock Text="{Binding Path=Size}" Width="80" HorizontalAlignment="Left" Margin="5,0,0,0"/>
< /StackPanel>
< /DataTemplate>

< /UserControl.Resources>
< Grid>

< ComboBox Margin="2,28,0,0" Name="cmbAutoComplete"
ItemsSource="{Binding}" ItemTemplate="{StaticResource cmbTemplate}" MaxDropDownHeight="200" Height="24" VerticalAlignment="Top">
< ComboBox.GroupStyle>
< GroupStyle>
< GroupStyle.HeaderTemplate>
< DataTemplate>
< StackPanel>
< Border BorderThickness="1" BorderBrush="Black">
< TextBlock Text="{Binding Items[0].FileType}" Background="AliceBlue"/>
< /Border>
< /StackPanel>
< /DataTemplate>
< /GroupStyle.HeaderTemplate>

< /GroupStyle>
< /ComboBox.GroupStyle>
< /ComboBox>
< TextBox Margin="2,28,0,0" Name="TextBox1" TextChanged="TextBox1_TextChanged" Height="24" VerticalAlignment="Top" />
< Label Margin="22,2,0,0" Name="Label1" Height="23" VerticalAlignment="Top" FontWeight="Bold" Foreground="DarkBlue" HorizontalAlignment="Left" Width="119">Enter Text Criteria< /Label>
< /Grid>
< /UserControl>




3rd Step, copy the following code and paste in the SearchControl.Xaml file.


Imports System.Collections.ObjectModel
Imports System.ComponentModel

''' < summary >
''' This class takes the path of the file which user can search and sees how big file it is.
''' < /summary >
''' < remarks>< /remarks>

Partial Public Class SearchControl

Private _threshold As Integer = 2

Private path As String = "C:\Vikas-Data\" ' set the path here which you want to search

Private items As ObservableCollection(Of AutoCompleteEntry)
Private view As IcollectionView

Public Sub New()

' This call is required by the Windows Form Designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.


items = New ObservableCollection(Of AutoCompleteEntry)

LoadPaths(New IO.DirectoryInfo(path))

view = CollectionViewSource.GetDefaultView(items)
view.GroupDescriptions.Add(New PropertyGroupDescription("FileType"))

cmbAutoComplete.DataContext = items

End Sub

Private Sub LoadPaths(ByVal dInfo As IO.DirectoryInfo)
Dim info As IO.DirectoryInfo

For Each info In dInfo.GetDirectories()
LoadPaths(info)
Next info


For Each fInfo As IO.FileInfo In dInfo.GetFiles()
items.Add(New AutoCompleteEntry(dInfo.FullName, fInfo))
Next fInfo

End Sub

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.TextChangedEventArgs)
Dim text As String


text = TextBox1.Text

If (text.Length < _threshold) Then

Else
view.Filter = New Predicate(Of Object)(AddressOf MyPredicate)

If (cmbAutoComplete.HasItems) Then
cmbAutoComplete.IsDropDownOpen = True
End If
End If
End Sub

Private Function MyPredicate(ByVal item As Object) As Boolean
Dim text As String
Dim itemEntry As AutoCompleteEntry

text = TextBox1.Text
itemEntry = TryCast(item, AutoCompleteEntry)

If (itemEntry.Name.IndexOf(text) > -1) Then
Return True
End If

Return False

End Function

End Class



The output is like following screenshot :



I entered "VB" and I had various file names in the collection which contain vb so it displayed file names grouped by the folder names.

Hope this article will help you!

Thanks,
Vikas

No comments: