简单的WPF下拉框过滤器

8
我已经在谷歌上搜索了一个简单的解决方案,但没有成功。我有一个标准的WPF组合框,我想根据用户在组合框获得焦点时输入的前2或3个字母来筛选显示的列表。我尝试了一些编码,包括一些lambda表达式,但是在指定"combobox.Items.Filter"这一行时,会抛出"System.NotSupportedException"错误。我没有使用MVVM,只希望为用户提供这个简单的功能。请帮忙!P.S.设置了IsEditable、IsTextSearchEnabled和StaysOpenOnEdit属性为true,但仍未实现所需功能。

你想让程序从可用列表中进行预测。 - Ankur Jyoti Phukan
组合框使用数据表填充,但列表有几百个选项。因此,当用户键入几个字符时,我需要缩短列表并打开选择。 - BabyDoll
我认为查询存在一些错误,请查看此链接... link - Ankur Jyoti Phukan
抱歉,我不太明白,你指的是哪个查询? - BabyDoll
请检查该链接...我认为你有类似的问题。 - Ankur Jyoti Phukan
当我尝试实现 .Items.Filter 方法时出现了错误,不确定那个链接与我的问题有什么关系,或者只是因为周日晚上太晚了? - BabyDoll
2个回答

24

我开发了一个示例应用程序。我使用字符串作为记录项,您可以使用自己的实体进行操作。退格键也正常工作。

 public class FilterViewModel
    {
        public IEnumerable<string> DataSource { get; set; }       

        public FilterViewModel()
        {
            DataSource = new[] { "india", "usa", "uk", "indonesia" };           
        }
    }

public partial class WinFilter : Window
    {
          public WinFilter()
          {
             InitializeComponent();

             FilterViewModel vm = new FilterViewModel();
             this.DataContext = vm;
          }

          private void Cmb_KeyUp(object sender, KeyEventArgs e)
          {
              CollectionView itemsViewOriginal = (CollectionView)CollectionViewSource.GetDefaultView(Cmb.ItemsSource);

              itemsViewOriginal.Filter = ((o) =>
              {
                  if (String.IsNullOrEmpty(Cmb.Text)) return true;
                  else
                  {
                     if (((string)o).Contains(Cmb.Text)) return true;
                     else return false;
                  }
              });

             itemsViewOriginal.Refresh();

             // if datasource is a DataView, then apply RowFilter as below and replace above logic with below one
             /* 
              DataView view = (DataView) Cmb.ItemsSource; 
              view.RowFilter = ("Name like '*" + Cmb.Text + "*'"); 
             */
          }
     }
XAML
<ComboBox x:Name="Cmb"
          IsTextSearchEnabled="False"
          IsEditable="True"
          ItemsSource="{Binding DataSource}"
          Width="120"
          IsDropDownOpen="True"
          StaysOpenOnEdit="True"
          KeyUp="Cmb_KeyUp" />

Output


@BabyDoll,你可能做了些傻事。你可以将你的代码上传到dropbox.com并分享链接。 - AnjumSKhan
我也这么认为!!或许值得一提的是,我是直接从datatable来绑定数据呢?因为我是WPF的初学者,所以肯定会有什么蠢问题我没想到。我在某个地方读到过,datatables不支持我现在这种过滤的方式,但这难道不正是我应该先使用ICollectionView的原因吗? - BabyDoll
@BabyDoll,你在 itemsViewOriginal 中获取了什么?CollectionView itemsViewOriginal = (CollectionView)CollectionViewSource.GetDefaultView(Cmb.ItemsSource); - AnjumSKhan
当我进行调试时,我可以看到数据表中的内容是正确的。有件事突然想到我了;我正在尝试过滤数据,但我没有指定要使用哪一列....这是我的问题吗?如果是,那么我该如何指定要用于过滤的列呢? - BabyDoll
在这行代码中 if (((string)o).Contains(Cmb.Text)) return true;o 给你提供了对象/数据库行/记录,你可以从中获取列/属性。 - AnjumSKhan
显示剩余6条评论

0

我认为CollectionView是你正在寻找的。

  public ObservableCollection<NdfClassViewModel> Classes
  {
      get { return _classes; }
  }

  public ICollectionView ClassesCollectionView
  {
      get
      {
          if (_classesCollectionView == null)
          {
              BuildClassesCollectionView();
          }
           return _classesCollectionView;
      }
  }

  private void BuildClassesCollectionView()
  {
      _classesCollectionView = CollectionViewSource.GetDefaultView(Classes);
      _classesCollectionView.Filter = FilterClasses;

      OnPropertyChanged(() => ClassesCollectionView);
  }

  public bool FilterClasses(object o)
  {
      var clas = o as NdfClassViewModel;



      // return true if object should be in list with applied filter, return flase if not
  }

你想把“ClassesCollectionView”作为你的ComboBox的ItemsSource。

谢谢回复!但是我仍然在指定combobox.Items.Filter的那一行遇到错误。 - BabyDoll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接