最近在一个WPF项目中用到一个下拉列表,随着用户输入字符而进行显示,使用了绑定等知识,虽然实现比较简单,可是在性能上也是想了很多办法终于才勉强可以用,与大家分享下。
用于页面绑定的模型类:
public class MainWindowModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Content> names = new ObservableCollection<Content>();
private bool popupIsOpen = false;
public bool PopupIsOpen
{
get
{
return popupIsOpen;
}
set
{
popupIsOpen = value;
this.PropertyChanged(this, new PropertyChangedEventArgs("PopupIsOpen"));
}
}
public ObservableCollection<Content> Names
{
get
{
return this.names;
}
set
{
this.names = value;
this.PropertyChanged(this, new PropertyChangedEventArgs("Names"));
}
}
}
public class Content
{
private string name=string.Empty;
public string Name
{
get
{
return this.name;
}
set
{
name = value;
}
}
}
后台代码:
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private MainWindowModel model = new MainWindowModel();
private List<BackgroundWorker> threadPool = new List<BackgroundWorker>();
public MainWindow()
{
InitializeComponent();
this.DataContext = model;
}
/// <summary>
/// 在此增加内容
/// </summary>
private void InitialSetValue()
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
this.model.Names.Clear();
for (int i = 0; i < 100; i++)
{
Content content = new Content();
content.Name = i.ToString() + i.ToString() +
i.ToString() + i.ToString() + i.ToString();
this.model.Names.Add(content);
}
}));
}
/// <summary>
/// 下拉菜单消失要清空内容
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void popupContent_Closed(object sender, EventArgs e)
{
this.model.Names.Clear();
}
/// <summary>
/// 文本框失去焦点,下拉列表隐藏
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textBox1_LostFocus(object sender, RoutedEventArgs e)
{
this.model.PopupIsOpen = false;
}
/// <summary>
/// 文字内容改变,下拉类表出现
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
this.model.PopupIsOpen = true;
if (threadPool.Count > 0)
{
threadPool[0].CancelAsync();
}
threadPool.Clear();
string key = this.textBox1.Text.Trim();
if (string.IsNullOrEmpty(key))
{
this.model.PopupIsOpen = false;
return;
}
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += (o, p) =>
{
InitialSetValue();
p.Result = this.model.Names;
};
worker.RunWorkerCompleted += (o, p) =>
{
this.model.Names = p.Result as ObservableCollection<Content>;
if (this.model.Names.Count <= 0)
{
this.model.PopupIsOpen = false;
}
};
threadPool.Add(worker);
Thread.Sleep(100);
if (threadPool.Count > 0)
{
threadPool[0].RunWorkerAsync();
}
}
/// <summary>
/// 子项被选中,下拉列表消失
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void item_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var data = (sender as ListBox).SelectedItem as Content;
if (data == null)
{
this.model.PopupIsOpen = false;
return;
}
try
{
this.textBox1.TextChanged -= new TextChangedEventHandler(textBox1_TextChanged);
var searchtext = data.Name;
this.model.PopupIsOpen = false;
}
catch
{
}
finally
{
this.textBox1.TextChanged += new TextChangedEventHandler(textBox1_TextChanged);
}
}
}
页面代码:
<Window x:Class="TestPopup.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Height="38" HorizontalAlignment="Left" Margin="71,89,0,0" LostFocus="textBox1_LostFocus" TextChanged="textBox1_TextChanged"
Name="textBox1" VerticalAlignment="Top" Width="236" />
<Popup Name="popupContent" StaysOpen="False" IsOpen="{Binding PopupIsOpen}" Closed="popupContent_Closed"
Placement="Bottom" PlacementTarget="{Binding ElementName=textBox1}" >
<ListBox Name="contentItems" SelectionChanged="item_SelectionChanged" ItemsSource="{Binding Names}"
MinWidth="{Binding ElementName=textBox1, Path=ActualWidth}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="5,5" FontSize="15" Text="{Binding Name}" Foreground="Gray"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Popup>
</Grid>
</Window>
效果:
主要注意的有一点,下拉列表消失时一定要清除数据,不然下次显示的时候会很慢。在用的时候找了好久才发现这个问题。
详细工程:http://download.csdn.net/detail/yysyangyangyangshan/4762184