2016-01-04 51 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