您的位置:首页 > 其它

WPF:下拉列表的简单实现

2012-11-13 13:55 323 查看
最近在一个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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: