2010-11-17 4 views
3

У меня есть элемент управления Listbox WPF, и я хотел бы разрешить пользователю изменять выбранный элемент с помощью типа «вперед». Поведение, которое я ищу, похоже на Windows Explorer. Когда вы продолжаете вводить текст имени папки, список будет продолжать выбирать более правильный элемент.Выбор элементов в списке WPF через клавиатуру Поиск типа «Ahead»

Например принять эту структуру папок:

OtherFolderName 
MyFirstFolder 
MyFirstFileFolder 
MyFirstList 

При выборе OtherFolderName с помощью мыши, а затем начните вводить MyFirstF пункт MyFirstFolder будет выбран, но если вы будете продолжать набирать MyFirstFi элемент MyFirstFileFolder будет выбран.

Мой список WPF не показывает этого, я надеюсь, что смогу его легко включить, так как это сделал старый список WinForms.

ответ

6

Посмотрите на классе TextSearch, определенно TextSearch.TextPath вложенного свойства:

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

TextSearch.TextPath свойство позволяет текстовый поиск и определяет, как извлечь текст для поиска из каждого пункта. В этом случае я предположил, что каждый из ваших объектов Folder имеет свойство «FolderName».

Если это не все, что вы ищете, вам, вероятно, придется реализовать свой собственный поиск, так как функция TextSearch не особенно удобна. Для этого:

  1. Обрабатывать событие TextInput
  2. Сравните время текущего TextInput с предшествующим TextInput. Если достаточно близко друг к другу, добавьте строку префикса, иначе установите ее на один символ.
  3. Искать все товары для данного префикса & если найдено установлено SelectedItem.

Я бы построил это как отдельный класс, используя прикрепленное свойство, похожее на встроенный класс TextSearch.

+1

Это именно то, что я искал. Благодарю. – Nate

0

Я использую скрытый текстовый блок, который появляется кратковременно, когда пользователь печатает, и сбрасывается через пару секунд и очищается, так что он не пытается совместить его содержимое после истечения таймера. Человек будет вводить ListBox, и его событие KeyUp заполнит TextBox из-за привязки на SearchText. Когда заполняется SearchText, он вызывает MyFilteredItems() для выполнения соответствия между этим текстом и ListBox. Затем, если человек нажимает 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)); 
    } 
}