代码之家  ›  专栏  ›  技术社区  ›  Nate CSS Guy

通过键盘“提前键入”搜索选择WPF列表框中的项目

  •  3
  • Nate CSS Guy  · 技术社区  · 15 年前

    我有一个WPF Listbox控件,我希望允许用户使用type ahead更改所选项目。我正在寻找的行为与windows资源管理器完全相同。当您继续键入文件夹名称的文本时,列表将继续选择更正确的项。

    例如,假设此文件夹结构:

    OtherFolderName
    MyFirstFolder
    MyFirstFileFolder
    MyFirstList
    

    如果你选择 OtherFolderName 用鼠标,然后开始键入 MyFirstF 项目 MyFirstFolder 将被选中,但如果继续键入 MyFirstFi 项目 MyFirstFileFolder 将被选中。

    我的WPF列表框没有显示这种行为,我希望我可以很容易地启用它,就像旧的WinForms列表框所做的那样。

    2 回复  |  直到 15 年前
        1
  •  7
  •   Ray Burns    15 年前

    查看TextSearch类,特别是附加的TextSearch.TextPath属性:

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

    text search.TextPath属性启用文本搜索并指定如何从每个项目中提取搜索文本。在本例中,我假设每个文件夹对象都有一个名为“FolderName”的属性。

    如果这不能实现你想要的所有功能,你可能需要实现你自己的搜索,因为TextSearch功能不是特别好用。为此:

    1. 处理TextInput事件
    2. 比较当前文本输入和以前文本输入的时间。如果靠得足够近,则追加到前缀字符串,否则将其设置为键入的单个字符。
    3. 在所有项目中搜索给定前缀&如果找到,请设置SelectedItem。

    我将使用附加属性将其构建为一个单独的类,类似于内置的TextSearch类。

        2
  •  0
  •   vapcguy    9 年前

    我使用的是一个隐藏的文本框,当用户输入时它会短暂出现,几秒钟后重置并清除,这样在计时器过期后它就不会尝试匹配其内容。这个人会在列表框中键入 KeyUp 事件将填充文本框,因为 SearchText . 什么时候? 搜索文本 充满了,就会触发 MyFilteredItems() 在该文本和列表框之间执行匹配。然后,如果此人按Enter键,则所选内容将进入另一个文本框(未在XAML中列出,但在代码中以注释形式提供)并从中清除 lstPickList . 然后清除文本框并重置计时器。

    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));
        }
    }
    
    推荐文章