2016-01-04 3 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, supplierCheckBox и subbieCheckBox. Это возвращает всех текущих поставщиков, которые также являются субподрядчиками.

Это все еще возвращает список из 5000 компаний, поэтому пользователь затем хочет использовать функцию поиска, чтобы найти компанию, которой они знают имя. Но он не ищет фильтр CompanyICollection, он сбрасывает его и фильтрует весь список (27000 компаний).

Я считаю, что проблема в том, что я создаю новый CompanyICollectionView.Fiilter каждый раз, когда я хочу найти существующий. Есть ли способ фильтровать уже отфильтрованный ICollectionView?

EDIT (Добавлено 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 к ObservableCollection, который поддерживает фильтрацию, т.е. FilteredObservableCollection ... посмотреть на: CollectionViewSource Filter not refreshed when Source is changed

Смежные вопросы