WPF实现TextBox输入文字后自动弹出数据(类似百度的输入框)

时间:2022-11-17 19:39:42

1. 创建一个继承至Canvas的控件,并命名为WPFAutoCompleteTextbox

2. 在WPFAutoCompleteTextbox.cs中增加以下代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFAutoCompleteTextbox
{
/// <summary>
/// Interaction logic for AutoCompleteTextBox.xaml
/// </summary>
public partial class AutoCompleteTextBox : Canvas
{
#region Members
private VisualCollection controls;
private TextBox textBox;
private ComboBox comboBox;
private ObservableCollection<AutoCompleteEntry> autoCompletionList;
private System.Timers.Timer keypressTimer;
private delegate void TextChangedCallback();
private bool insertText;
private int delayTime;
private int searchThreshold;
#endregion

#region Constructor
public AutoCompleteTextBox()
{
controls = new VisualCollection(this);
InitializeComponent();

autoCompletionList = new ObservableCollection<AutoCompleteEntry>();
searchThreshold = 2; // default threshold to 2 char

// set up the key press timer
keypressTimer = new System.Timers.Timer();
keypressTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);

// set up the text box and the combo box
comboBox = new ComboBox();
comboBox.IsSynchronizedWithCurrentItem = true;
comboBox.IsTabStop = false;
comboBox.SelectionChanged += new SelectionChangedEventHandler(comboBox_SelectionChanged);

textBox = new TextBox();
textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
textBox.VerticalContentAlignment = VerticalAlignment.Center;

controls.Add(comboBox);
controls.Add(textBox);
}
#endregion

#region Methods
public string Text
{
get { return textBox.Text; }
set
{
insertText = true;
textBox.Text = value;
}
}

public int DelayTime
{
get { return delayTime; }
set { delayTime = value; }
}

public int Threshold
{
get { return searchThreshold; }
set { searchThreshold = value; }
}

public void AddItem(AutoCompleteEntry entry)
{
autoCompletionList.Add(entry);
}

private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (null != comboBox.SelectedItem)
{
insertText = true;
ComboBoxItem cbItem = (ComboBoxItem)comboBox.SelectedItem;
textBox.Text = cbItem.Content.ToString();
}
}

private void TextChanged()
{
try
{
comboBox.Items.Clear();
if (textBox.Text.Length >= searchThreshold)
{
foreach (AutoCompleteEntry entry in autoCompletionList)
{
foreach (string word in entry.KeywordStrings)
{
if (word.StartsWith(textBox.Text, StringComparison.CurrentCultureIgnoreCase))
{
ComboBoxItem cbItem = new ComboBoxItem();
cbItem.Content = entry.ToString();
comboBox.Items.Add(cbItem);
break;
}
}
}
comboBox.IsDropDownOpen = comboBox.HasItems;
}
else
{
comboBox.IsDropDownOpen = false;
}
}
catch { }
}

private void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)
{
keypressTimer.Stop();
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new TextChangedCallback(this.TextChanged));
}

private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
// text was not typed, do nothing and consume the flag
if (insertText == true) insertText = false;

// if the delay time is set, delay handling of text changed
else
{
if (delayTime > 0)
{
keypressTimer.Interval = delayTime;
keypressTimer.Start();
}
else TextChanged();
}
}

protected override Size ArrangeOverride(Size arrangeSize)
{
textBox.Arrange(new Rect(arrangeSize));
comboBox.Arrange(new Rect(arrangeSize));
return base.ArrangeOverride(arrangeSize);
}

protected override Visual GetVisualChild(int index)
{
return controls[index];
}

protected override int VisualChildrenCount
{
get { return controls.Count; }
}
#endregion
}
}

3. 在WPFAutoCompleteTextbox.xaml中增加以下代码
<Canvas x:Class="WPFAutoCompleteTextbox.AutoCompleteTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Canvas>

4. 使用创建的WPFAutoCompleteTextbox,新建一个WPF工程,在Windows1.xaml中按以下代码编写
<Window x:Class="WPFAutoCompleteTextbox.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFAutoCompleteTextbox"
Title="WPF AutoCompleteTextBox" Height="200" Width="300">
<StackPanel Background="SteelBlue">
<Button Name="button1" Height="23" Width="75" Margin="20" Click="button1_Click" HorizontalAlignment="Left">Clear</Button>
<local:AutoCompleteTextBox Height="23" Width="240" x:Name="textBox1" DelayTime="500" Threshold="2"/>
</StackPanel>
</Window>

5. 在Windows1.cs中按以下代码编写
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFAutoCompleteTextbox
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
textBox1.AddItem(new AutoCompleteEntry("Toyota Camry", "Toyota Camry", "camry", "car", "sedan"));
textBox1.AddItem(new AutoCompleteEntry("Toyota Corolla", "Toyota Corolla", "corolla", "car", "compact"));
textBox1.AddItem(new AutoCompleteEntry("Toyota Tundra", "Toyota Tundra", "tundra", "truck"));
textBox1.AddItem(new AutoCompleteEntry("Chevy Impala", null)); // null matching string will default with just the name
textBox1.AddItem(new AutoCompleteEntry("Chevy Tahoe", "Chevy Tahoe", "tahoe", "truck", "SUV"));
textBox1.AddItem(new AutoCompleteEntry("Chevrolet Malibu", "Chevrolet Malibu", "malibu", "car", "sedan"));
}

private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = string.Empty;
}
}
}

6. 编译工程,哈哈,看到效果了吧