Reputation:
Is it possible to make a textbox autocomplete in WPF?
I found a sample where a combo box is used and the triangle is removed by editing the style template.
Is there a better solution?
Upvotes: 57
Views: 131453
Reputation: 815
Here a way by using WPF PopUp element with a textBox :
XAML file
<TextBox x:Name="DocumentType"
Margin="20"
KeyUp="DocumentType_KeyUp"
LostFocus="DocumentType_LostFocus"/>
<Popup x:Name="autoCompletorListPopup"
Visibility="Collapsed"
StaysOpen="False"
AllowsTransparency="True"
PlacementTarget="{Binding ElementName=DocumentType}"
Width="150"
Placement="Bottom">
<ListBox x:Name="autoCompletorList"
Background="WhiteSmoke"
MaxHeight="200"
Margin="20 0"
SelectionChanged="autoCompletorList_SelectionChanged"/>
</Popup>
CS file
List<string> listDocumentType = new List<string>() {"Pdf File","AVI File","JPEG file","MP3 sound","MP4 Video"} //...
private void autoCompletorList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (autoCompletorList.SelectedItem != null)
{
DocumentType.Text = autoCompletorList.SelectedValue.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void DocumentType_KeyUp(object sender, KeyEventArgs e)
{
try
{
if(e.Key == Key.Enter)
{
// change focus or remove focus on this element
NextElementBox.Focus();
}
else
{
if (DocumentType.Text.Trim() != "")
{
autoCompletorListPopup.IsOpen = true;
autoCompletorListPopup.Visibility = Visibility.Visible;
autoCompletorList.ItemsSource = listDocumentType.Where(td => td.Trim().ToLower().Contains(DocumentType.Text.Trim().ToLower()));
}
else
{
autoCompletorListPopup.IsOpen = false;
autoCompletorListPopup.Visibility = Visibility.Collapsed;
autoCompletorList.ItemsSource = null;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void DocumentType_LostFocus(object sender, RoutedEventArgs e)
{
try
{
if (autoCompletorList.SelectedItem != null)
{
DocumentType.Text = autoCompletorList.SelectedValue.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Upvotes: 1
Reputation: 80
I'm surprised why no one suggested to use the WinForms Textbox.
XAML:
<WindowsFormsHost Margin="10" Width="70">
<wf:TextBox x:Name="textbox1"/>
</WindowsFormsHost>
Also don't forget the Winforms Namespace:
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
C#:
AutoCompleteStringCollection stringCollection = new AutoCompleteStringCollection(){"String 1", "String 2", "etc..."};
textbox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
textbox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
textbox1.AutoCompleteCustomSource = stringCollection;
With Autocomplete, you need to do it in the Code behind, because for some reasons, others might can explain, it throws an exception.
Upvotes: 1
Reputation: 7352
If you have a small number of values to auto complete, you can simply add them in xaml. Typing will invoke auto-complete, plus you have dropdowns too.
<ComboBox Text="{Binding CheckSeconds, UpdateSourceTrigger=PropertyChanged}"
IsEditable="True">
<ComboBoxItem Content="60"/>
<ComboBoxItem Content="120"/>
<ComboBoxItem Content="180"/>
<ComboBoxItem Content="300"/>
<ComboBoxItem Content="900"/>
</ComboBox>
Upvotes: 3
Reputation: 315
I know this is a very old question but I want to add an answer I have come up with.
First you need a handler for your normal TextChanged
event handler for the TextBox
:
private bool InProg;
internal void TBTextChanged(object sender, TextChangedEventArgs e)
{
var change = e.Changes.FirstOrDefault();
if ( !InProg )
{
InProg = true;
var culture = new CultureInfo(CultureInfo.CurrentCulture.Name);
var source = ( (TextBox)sender );
if ( ( ( change.AddedLength - change.RemovedLength ) > 0 || source.Text.Length > 0 ) && !DelKeyPressed )
{
if ( Files.Where(x => x.IndexOf(source.Text, StringComparison.CurrentCultureIgnoreCase) == 0 ).Count() > 0 )
{
var _appendtxt = Files.FirstOrDefault(ap => ( culture.CompareInfo.IndexOf(ap, source.Text, CompareOptions.IgnoreCase) == 0 ));
_appendtxt = _appendtxt.Remove(0, change.Offset + 1);
source.Text += _appendtxt;
source.SelectionStart = change.Offset + 1;
source.SelectionLength = source.Text.Length;
}
}
InProg = false;
}
}
Then make a simple PreviewKeyDown
handler:
private static bool DelKeyPressed;
internal static void DelPressed(object sender, KeyEventArgs e)
{ if ( e.Key == Key.Back ) { DelKeyPressed = true; } else { DelKeyPressed = false; } }
In this example "Files" is a list of directory names created on application startup.
Then just attach the handlers:
public class YourClass
{
public YourClass()
{
YourTextbox.PreviewKeyDown += DelPressed;
YourTextbox.TextChanged += TBTextChanged;
}
}
With this whatever you choose to put in the List
will be used for the autocomplete box. This may not be a great option if you expect to have an enormous list for the autocomplete but in my app it only ever sees 20-50 items so it cycles through very quick.
Upvotes: 4
Reputation: 5665
Nimgoble's is the version I used in 2015. Thought I'd put it here as this question was top of the list in google for "wpf autocomplete textbox"
Install nuget package for project in Visual Studio
Add a reference to the library in the xaml:
xmlns:behaviors="clr-namespace:WPFTextBoxAutoComplete;assembly=WPFTextBoxAutoComplete"
Create a textbox and bind the AutoCompleteBehaviour to List<String>
(TestItems):
<TextBox Text="{Binding TestText, UpdateSourceTrigger=PropertyChanged}"
behaviors:AutoCompleteBehavior.AutoCompleteItemsSource="{Binding TestItems}" />
IMHO this is much easier to get started and manage than the other options listed above.
Upvotes: 13
Reputation: 4846
You can find one in the WPF Toolkit, which is also available via NuGet.
This article demos how to create a textbox which can auto-suggest items at runtime based on input, in this case, disk drive folders. WPF AutoComplete Folder TextBox
Also take a look at this nice Reusable WPF Autocomplete TextBox, it was for me very usable.
Upvotes: 41
Reputation: 1064
or you can add the AutoCompleteBox into the toolbox by clicking on it and then Choose Items, go to WPF Components, type in the filter AutoCompleteBox, which is on the System.Windows.Controls namespace and the just drag into your xaml file. This is way much easier than doing these other stuff, since the AutoCompleteBox is a native control.
Upvotes: 4