2016-01-04 54 views
1

我目前有一个DataGrid充满公司,我过滤的基础上有两件事 - 一个是搜索框,用户可以根据公司的名称,城镇或邮政编码进行过滤。这看起来像这样;过滤和ICollectionView过滤器WPF

通过名称/镇过滤/邮编

 private void FilterDataGrid() 
     { 
      try 
      { 
       var searchText = CharactersOnly(searchBox.Text); 
       CompanyICollectionView.Filter = (obj => 
       { 
        CompanyModel compDetails = obj as CompanyModel; 
        if (compDetails == null) 
        { 
         return true; 
        } 

        if (compNameRad.IsChecked == true) 
        { 
         return CompanyContains(compDetails.Name, searchText.ToLower()); 
        } 
        if (compTownRad.IsChecked == true) 
        { 
         return CompanyContains(compDetails.Town, searchText.ToLower()); 
        } 
        if (compPcodeRad.IsChecked == true) 
        { 
         return CompanyContains(compDetails.Postcode, searchText.ToLower()); 
        } 
        return false; 
       }); 

       if (dataGrid.Items.Count == 0) // There are no companies with this filter on, clear the label 
       { 
        compDetailsLabel.Content = string.Empty; 
       } 
       else 
       { 
        dataGrid.SelectedIndex = 0; 
       } 
      } 
      catch (Exception ex) 
      { 
       var hEs = new HandleExceptionService(); 
       hEs.HandleException(ex.ToString()); 
      } 
     } 

用于过滤的第二种方法是基于对本公司的类型。这是通过选择多个CheckBoxes完成的。这个方法看起来像这样;

按公司类型

private void FilterCompanyType(object sender, RoutedEventArgs e) 
    { 
     criteria.Clear(); 

     if (currentCheckBox.IsChecked == true && nonCurrentCheckBox.IsChecked == false) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.CurrentStatus == 1)); 
     } 
     else if (nonCurrentCheckBox.IsChecked == true && currentCheckBox.IsChecked == false) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.CurrentStatus == 0)); 
     } 
     else if (nonCurrentCheckBox.IsChecked == true && currentCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => (x.CurrentStatus == 1 || x.CurrentStatus == 0))); 
     } 

     if (subbieCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.Subcontractor == 1)); 
     } 

     if (supplierCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.Supplier == 1)); 
     } 

     if (planthireCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.Planthire == 1)); 
     } 

     if (architectCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.Architect == 1)); 
     } 

     if (qsCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.QS == 1)); 
     } 

     if (projectManagerCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.ProjectManager == 1)); 
     } 

     if (structEngCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.StructEng == 1)); 
     } 

     if (servEngCheckBox.IsChecked == true) 
     { 
      criteria.Add(new Predicate<CompanyModel>(x => x.ServiceEng == 1)); 
     } 

     foreach (CheckBox checkBox in companyFilters.Children) 
     { 
      if (!CheckCheckBoxes()) 
      { 
       dataGrid.ItemsSource = null; 
       compDetailsLabel.Content = string.Empty; 
      } 
      else 
      { 
       dataGrid.ItemsSource = CompanyICollectionView; 
       CompanyICollectionView.Filter = dynamic_Filter; 
       SetSelectedCompany(selectedIndex); 
       dataGrid.SelectedIndex = 0; 
      } 
     } 

     var nfi = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone(); 
     nfi.NumberGroupSeparator = ","; 
     numberOfCompaniesLabel.Content = "Number of Companies: " + dataGrid.Items.Count.ToString("#,#", nfi); 
    } 

这两种过滤方式过滤器看起来不错自己。当我想过滤已经应用到DataGrid的过滤器时,问题就出现了。例如,用户想要过滤公司类型,因此他们选择currentCheckBox,supplierCheckBoxsubbieCheckBox。这将返回所有也是分包商的当前供应商。

这仍返回5000家公司的列表,因此用户然后想要使用搜索功能来查找他们知道的公司的名称。但它不搜索已过滤的CompanyICollection,它重置它并过滤整个列表(27000家公司)。

我相信问题是我每次创建一个新的CompanyICollectionView.Fiilter,当我想搜索一个现有的。有没有办法过滤已经过滤的ICollectionView

编辑(新增dynamic_Filter)

 private bool dynamic_Filter(object item) 
     { 
      CompanyModel company = item as CompanyModel; 
      bool isIn = true; 
      if (criteria.Count() == 0) 
       return isIn; 
      isIn = criteria.TrueForAll(x => x(company)); 
      return isIn; 
     } 
+0

你使用两个滤波器相同的项目源? – ZwoRmi

+0

'DataGrid'具有相同的'ItemsSource'是的,('CompanyICollectionView') – CBreeze

+0

哪里来自'dynamic_Filter'?从“标准”创建? – ZwoRmi

回答

1

你是对的,问题是,你重置每一次过滤器。所以,你需要做一些modificatons解决您的问题(我将承担所有的代码是在同一类):

private bool filterCompanyInfos(object o){ 
    //Function which return true if selected info and filter (name, town, code,...) corresponds to the object o (casted as a CompanyModel) 
    //I let you write this part, should be like the filterCompanyType method. 
} 

private bool filterCompanyType(object o){ 
    criteria.Clear(); 

    if (currentCheckBox.IsChecked == true && nonCurrentCheckBox.IsChecked == false) 
    { 
     criteria.Add(new Predicate<CompanyModel>(x => x.CurrentStatus == 1)); 
    } 
    else if (nonCurrentCheckBox.IsChecked == true && currentCheckBox.IsChecked == false) 
    { 
     criteria.Add(new Predicate<CompanyModel>(x => x.CurrentStatus == 0)); 
    } 
    else if (nonCurrentCheckBox.IsChecked == true && currentCheckBox.IsChecked == true) 
    { 
     criteria.Add(new Predicate<CompanyModel>(x => (x.CurrentStatus == 1 || x.CurrentStatus == 0))); 
    } 
    //.... All other criterias here 

    CompanyModel company = o as CompanyModel; 
    bool isIn = true; 
    if (criteria.Count() == 0) 
     return isIn; 
    isIn = criteria.TrueForAll(x => x(company)); 
    return isIn; 
} 

private bool FilterCompany(object o){ 
    return filterCompanyType(o) && filterCompanyInfos(o) 
} 


public void ApplyFilter(CollectionView companyCollectionView){ 
    CompanyICollectionView.Filter = this.FilterCompany; 
    //do some other stuff like selected index ... 
} 
+0

谢谢你的回答。我对“FilterCompanyInfos”有点不确定。这和我的方法一样,用户可以搜索名称,城镇,代码等吗?或者该部分是否也需要在'FilterCompanyType'内部? – CBreeze

+0

filterCompanyInfos方法是关于按名称/城镇/邮政编码过滤。您需要对其进行调整,以便在尊重过滤器的情况下,此功能对物体返回true – ZwoRmi

+0

如何比较对象以确保它与已选择的过滤器相匹配? – CBreeze

1

没有需要每次都重新创建过滤器属性更改。 您最好做的是将两个过滤器合并到一个功能中,将其传递给CompanyICollectionView.Filter,并从属性更改事件中调用CompanyICollectionView.Refresh();。 你甚至可以绑定你的CollectionView到支持过滤即FilteredObservableCollection一个ObservableCollection ... 看看: CollectionViewSource Filter not refreshed when Source is changed