WPF:下拉列表的簡單實現


最近在一個WPF項目中用到一個下拉列表,隨着用戶輸入字符而進行顯示,使用了綁定等知識,雖然實現比較簡單,可是在性能上也是想了很多辦法終於才勉強可以用,與大家分享下。

用於頁面綁定的模型類:

 1 public class MainWindowModel : INotifyPropertyChanged
 2     {
 3         public event PropertyChangedEventHandler PropertyChanged;
 4 
 5         private ObservableCollection<Content> names = new ObservableCollection<Content>();
 6 
 7         private bool popupIsOpen = false;
 8 
 9         public bool PopupIsOpen
10         {
11             get 
12             { 
13                 return popupIsOpen;
14             }
15 
16             set 
17             { 
18                 popupIsOpen = value;
19 
20                 this.PropertyChanged(this, new PropertyChangedEventArgs("PopupIsOpen"));
21             }
22         }
23 
24         public ObservableCollection<Content> Names
25         {
26             get
27             {
28                 return this.names;
29             }
30 
31             set
32             {
33                 this.names = value;
34 
35                 this.PropertyChanged(this, new PropertyChangedEventArgs("Names"));
36             }
37         }
38     }
39 
40     public class Content
41     {
42         private string name=string.Empty;
43 
44         public string Name
45         {
46             get
47             {
48                 return this.name;
49             }
50 
51             set
52             {
53                 name = value;
54             }
55         }
56     }

 后台代碼:

  1 /// <summary>
  2     /// MainWindow.xaml 的交互邏輯
  3     /// </summary>
  4     public partial class MainWindow : Window
  5     {
  6         private MainWindowModel model = new MainWindowModel();
  7 
  8         private List<BackgroundWorker> threadPool = new List<BackgroundWorker>();
  9 
 10         public MainWindow()
 11         {
 12             InitializeComponent();
 13 
 14             this.DataContext = model;
 15         }
 16 
 17         /// <summary>
 18         /// 在此增加內容
 19         /// </summary>
 20         private void InitialSetValue()
 21         {
 22             this.Dispatcher.BeginInvoke(new Action(() =>
 23                 {
 24                     this.model.Names.Clear();
 25 
 26                     for (int i = 0; i < 100; i++)
 27                     {
 28                         Content content = new Content();
 29 
 30                         content.Name = i.ToString() + i.ToString() + 
 31                             i.ToString() + i.ToString() + i.ToString();
 32 
 33                         this.model.Names.Add(content);
 34                     }
 35                 }));
 36         }
 37 
 38         /// <summary>
 39         /// 下拉菜單消失要清空內容
 40         /// </summary>
 41         /// <param name="sender"></param>
 42         /// <param name="e"></param>
 43         private void popupContent_Closed(object sender, EventArgs e)
 44         {
 45             this.model.Names.Clear();
 46         }
 47 
 48         /// <summary>
 49         /// 文本框失去焦點,下拉列表隱藏
 50         /// </summary>
 51         /// <param name="sender"></param>
 52         /// <param name="e"></param>
 53         private void textBox1_LostFocus(object sender, RoutedEventArgs e)
 54         {
 55             this.model.PopupIsOpen = false;
 56         }
 57 
 58         /// <summary>
 59         /// 文字內容改變,下拉類表出現
 60         /// </summary>
 61         /// <param name="sender"></param>
 62         /// <param name="e"></param>
 63         private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
 64         {
 65             this.model.PopupIsOpen = true;
 66 
 67             if (threadPool.Count > 0)
 68             {
 69                 threadPool[0].CancelAsync();
 70             }
 71 
 72             threadPool.Clear();
 73 
 74             string key = this.textBox1.Text.Trim();
 75 
 76             if (string.IsNullOrEmpty(key))
 77             {
 78                 this.model.PopupIsOpen = false;
 79 
 80                 return;
 81             }
 82 
 83             BackgroundWorker worker = new BackgroundWorker();
 84 
 85             worker.WorkerReportsProgress = true;
 86 
 87             worker.WorkerSupportsCancellation = true;
 88 
 89             worker.DoWork += (o, p) =>
 90             {
 91                 InitialSetValue();
 92 
 93                 p.Result = this.model.Names;
 94             };
 95 
 96             worker.RunWorkerCompleted += (o, p) =>
 97             {
 98                 this.model.Names = p.Result as ObservableCollection<Content>;
 99 
100                 if (this.model.Names.Count <= 0)
101                 {
102                     this.model.PopupIsOpen = false;
103                 }
104             };
105 
106             threadPool.Add(worker);
107 
108             Thread.Sleep(100);
109 
110             if (threadPool.Count > 0)
111             {
112                 threadPool[0].RunWorkerAsync();
113             }
114         }
115 
116         /// <summary>
117         /// 子項被選中,下拉列表消失
118         /// </summary>
119         /// <param name="sender"></param>
120         /// <param name="e"></param>
121         private void item_SelectionChanged(object sender, SelectionChangedEventArgs e)
122         {
123             var data = (sender as ListBox).SelectedItem as Content;
124 
125             if (data == null)
126             {
127                 this.model.PopupIsOpen = false;
128 
129                 return;
130             }
131 
132             try
133             {
134                 this.textBox1.TextChanged -= new TextChangedEventHandler(textBox1_TextChanged);
135 
136                 var searchtext = data.Name;
137 
138                 this.model.PopupIsOpen = false;
139             }
140             catch
141             {
142             }
143             finally
144             {
145                 this.textBox1.TextChanged += new TextChangedEventHandler(textBox1_TextChanged);
146             }
147         }
148     }

頁面代碼:

 <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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM