您的位置:首页 > 其它

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

2016-06-01 15:42 946 查看
1、添加一个数据实体类 AutoCompleteEntry,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FCClient.AppCode
{
public class AutoCompleteEntry
{
private string[] keywordStrings;
private string displayString;

public string[] KeywordStrings
{
get
{
if (keywordStrings == null)
{
keywordStrings = new string[] { displayString };
}
return keywordStrings;
}
}

public string DisplayName
{
get { return displayString; }
set { displayString = value; }
}

public AutoCompleteEntry(string name, params string[] keywords)
{
displayString = name;
keywordStrings = keywords;
}

public override string ToString()
{
return displayString;
}
}
}


2、创建一个继承至Canvas的控件,并命名为AutoCompleteTextBox,前台 AutoCompleteTextBox.xam l代码,如下:

<Canvas x:Class="FCClient.CustomControls.AutoCompleteTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="30" Width="300">
</Canvas>


3、后台 AutoCompleteTextBox 代码,如下:

using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Timers;

using FCClient.AppCode;

namespace FCClient.CustomControls
{
/// <summary>
/// 自定义自动匹配文本框
/// </summary>
public partial class AutoCompleteTextBox : Canvas
{
#region 成员变量

private VisualCollection controls;
private TextBox textBox;
private ComboBox comboBox;
private ObservableCollection<AutoCompleteEntry> autoCompletionList;
private Timer keypressTimer;
private delegate void TextChangedCallback();
private bool insertText;
private int delayTime;
private int searchThreshold;

#endregion 成员变量

#region 构造函数

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

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

// 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;
Panel.SetZIndex(comboBox, -1);
comboBox.SelectionChanged += new SelectionChangedEventHandler(comboBox_SelectionChanged);

textBox = new TextBox();
textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
textBox.GotFocus += new RoutedEventHandler(textBox_GotFocus);
textBox.KeyUp += new KeyEventHandler(textBox_KeyUp);
textBox.KeyDown += new KeyEventHandler(textBox_KeyDown);
textBox.VerticalContentAlignment = VerticalAlignment.Center;

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

#endregion 构造函数

#region 成员方法

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; }
}

/// <summary>
/// 添加Item
/// </summary>
/// <param name="entry"></param>
public void AddItem(AutoCompleteEntry entry)
{
autoCompletionList.Add(entry);
}

/// <summary>
/// 清空Item
/// </summary>
/// <param name="entry"></param>
public void ClearItem()
{
autoCompletionList.Clear();
}

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.Contains(textBox.Text))
{
ComboBoxItem cbItem = new ComboBoxItem();
cbItem.Content = entry.ToString();
comboBox.Items.Add(cbItem);
break;
}
//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();
}
}

//获得焦点时
public void textBox_GotFocus(object sender, RoutedEventArgs 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();
}
}

public void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (textBox.IsInputMethodEnabled == true)
{
comboBox.IsDropDownOpen = false;
}
}

/// <summary>
/// 按向下按键时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Down && comboBox.IsDropDownOpen == true)
{
comboBox.Focus();
}
}

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 成员方法
}
}


4.、使用创建的 AutoCompleteTextbox ,新建一个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="195" Width="561">
<Grid Background="SteelBlue">
<Button Name="button1" Height="23" Width="75" Margin="12,12,0,0" Click="button1_Click"
           HorizontalAlignment="Left" VerticalAlignment="Top">Clear</Button>
<local:AutoCompleteTextBox Height="23" Width="162" x:Name="textBox1" Margin="25,65,0,0"
           HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
</Window>


5、 在 Windows1.cs 中初始化搜索数据,如下:

public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
textBox1.AddItem(new AutoCompleteEntry("上海", null));
textBox1.AddItem(new AutoCompleteEntry("北京", null));
textBox1.AddItem(new AutoCompleteEntry("济南", null));
textBox1.AddItem(new AutoCompleteEntry("青岛", null));
textBox1.AddItem(new AutoCompleteEntry("天津", null));
textBox1.AddItem(new AutoCompleteEntry("黑龙江", null));
textBox1.AddItem(new AutoCompleteEntry("聊城", null));
}

private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = string.Empty;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: