2010-11-17 29 views
3

我有一個WPF列表框控件,我希望允許用戶使用輸入提前更改所選項目。我正在尋找的行爲與Windows資源管理器完全相同。繼續鍵入文件夾名稱的文本時,列表將繼續選擇更正確的項目。通過鍵盤「預先輸入」搜索在WPF列表框中選擇項目

例如,假設該文件夾結構:

OtherFolderName 
MyFirstFolder 
MyFirstFileFolder 
MyFirstList 

如果選擇OtherFolderName用鼠標,然後開始鍵入MyFirstFMyFirstFolder將被選擇的項目,但如果你繼續鍵入MyFirstFi項目MyFirstFileFolder將被選中。

我的WPF列表框沒有表現出這種行爲,我希望我可以很容易地啓用它,因爲舊的WinForms列表框就是這樣做的。

回答

6

看看在文本搜索類,特別是TextSearch.TextPath附加屬性:

<ListBox TextSearch.TextPath="FolderName" ... /> 

的TextSearch.TextPath屬性使文本搜索並指定如何提取從每個項目中搜索文本。在這種情況下,我假定每個Folder對象都有一個名爲「FolderName」的屬性。

如果這不能滿足您的所有需求,您可能必須執行自己的搜索,因爲TextSearch功能不是特別可調整的。要做到這一點:

  1. 處理TextInput事件
  2. 比較現有的TextInput當前的TextInput的時間。如果足夠接近,則附加到前綴字符串,否則將其設置爲鍵入的單個字符。
  3. 搜索所有項目給定的前綴&如果發現設置SelectedItem。

我會使用類似於內置TextSearch類的附加屬性將它構建爲一個單獨的類。

+1

這正是我一直在尋找。謝謝。 – Nate 2010-11-17 23:43:27

0

我使用一個隱藏的文本框,在用戶輸入時短暫出現,並在幾秒鐘後重置並清除,以便在定時器到期後不嘗試匹配其內容。該人將輸入列表框,並且由於在SearchText上的綁定,其事件將填充文本框。當SearchText被填充時,它觸發MyFilteredItems()在該文本和列表框之間執行匹配。然後,如果用戶按Enter,則選擇將進入另一個TextBox(未在XAML中列出,但在代碼中註釋時提供),並從lstPickList中清除。 TextBox然後被清除並且定時器重置。

XAML:

<TextBox Name="txtPicker" IsReadOnly="True" Foreground="LightGreen" FontFamily="Consolas" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}"></TextBox> 

<ListBox Name="lstPickList" Grid.Row="1" ItemsSource="{Binding MyFilteredItems}" KeyUp="lstPickList_KeyUp"></ListBox> 

然後這是相關的代碼隱藏:

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    private Timer t = new Timer();  
    public System.Windows.Threading.DispatcherTimer tCleanup = 
     new System.Windows.Threading.DispatcherTimer(); 

    private string _searchText; 
    public string SearchText 
    { 
     get { return _searchText; } 
     set 
     { 
      _searchText = value; 

      OnPropertyChanged("SearchText"); 
      OnPropertyChanged("MyFilteredItems"); 
     } 
    } 

    public List<string> MyItems { get; set; }   

    public IEnumerable<string> MyFilteredItems 
    { 
     get 
     { 
      if (SearchText == null) return MyItems; 

      return MyItems.Where(x => x.ToUpper().StartsWith(SearchText.ToUpper())); 
     }    
    } 


    public MainWindow() 
    { 
     InitializeComponent(); 

     MyItems = new List<string>() { "ABC", "DEF", "GHI" };      
     this.DataContext = this; 

     t.Interval = 1000; 
     t.Elapsed += new ElapsedEventHandler(timerCounter); 
     tCleanup.Interval = new TimeSpan(0,0,1); 
     tCleanup.Tick += new EventHandler(cleanupCounter_Tick);   
     txtPicker.Visibility = Visibility.Collapsed; 
     tCleanup.Start(); 
    } 
    private static int counter = 0; 
    protected void timerCounter(object sender, ElaspedEventArgs e) 
    { 
     counter++; 
    } 

    protected void cleanupCounter_Tick(object sender, EventArgs e) 
    { 
     if (counter > 2 && txtPicker.Visibility == Visibility.Visible) 
      txtPicker.Visibility = Visibility.Collapsed; 
    } 

    private void lstPickList_KeyUp(object sender, KeyEventArgs e) 
    { 
     ListBox lst = (ListBox)sender; 
     string strg = Convert.ToString(e.Key.ToString().Replace("D","")); 
     if (counter < 2) 
     { 
      txtPicker.Visibility = Visibility.Visible; 
      t.Start(); 
      if (strg == "Return") 
      { 
       txtPicker.Text += "{Enter}"; 
       SearchText += "{Enter}"; 
      } 
      else 
      { 
       txtPicker.Text += strg; 
       SearchText += strg; 
      } 
     } 
     else 
     { 
      SearchText = strg; 
      txtPicker.Text = strg; 
      t.Stop(); 
      counter = 0; 
      t.Start(); 
     } 

     if (strg == "Return") 
     { 
      // This next line would be if you had a "selected items" ListBox to store the item 
      // lstSelectedList.Items.Add(lstPickList.SelectedItem); 
      lstPickList.Items.Remove(lstPickList.SelectedItem); 
      t.Stop(); 
      txtPicker.Visibility = Visibility.Collapsed; 
      counter = 0; 
      txtPicker.Text = String.Empty; 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    void OnPropertyChanged(string name) 
    { 
     if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); 
    } 
} 
相關問題