过滤和ICollectionView过滤WPF

时间:2016-01-04 09:56:21

标签: c# wpf filter datagrid

我目前有一个DataGrid填充了我根据两件事过滤的公司 - 一个是用户可以根据公司名称,城镇或邮政编码过滤的搜索框。这看起来像这样;

按名称/城镇/邮政编码过滤

        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的过滤器时,会出现问题。例如,用户想要过滤公司类型,因此他们会选择currentCheckBoxsupplierCheckBoxsubbieCheckBox。这将返回所有当前也是分包商的供应商。

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

我认为问题在于,每当我想搜索现有的CompanyICollectionView.Fiilter时,我就会创建一个新的ICollectionView。有没有办法过滤已经过滤的 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; }

编辑(已添加dynamic_Filter)

public SettingsDto uploadInChunck(Connection conn, SettingsDto oSettingsDto)throws Exception{
    SettingsDto objSettingsDto = new SettingsDto();
    List<SettingsDto> lstObj = null;
    FileChannel fc =null;
    File file = null;
    file = new File(oSettingsDto.getFormFile().getOriginalFilename());
    oSettingsDto.getFormFile().transferTo(file);
    RandomAccessFile raf = new RandomAccessFile(file, "r");
    fc = raf.getChannel();
    long startTime = System.currentTimeMillis();
        try{
            ByteBuffer buffer = ByteBuffer.allocate(512);
            StringBuilder sb = new StringBuilder();
            while(fc.read(buffer) > 0)
            {
                buffer.flip();
                for (int i = 0; i < buffer.limit(); i++)
                {
                    sb.append((char) buffer.get());
                }

                String[] strArr = sb.toString().split("\\n");

                if(null != oSettingsDto.getUploadFileTemplate() && oSettingsDto.getUploadFileTemplate().equals("Open Order Data")){
                    settingsDao.updateOpenOrdData(conn, strArr);
                } else if(null != oSettingsDto.getUploadFileTemplate() && oSettingsDto.getUploadFileTemplate().equals("Shipment Forecast Data")){
                    settingsDao.updateShipmentForcastData(conn, strArr);
                }else if(null != oSettingsDto.getUploadFileTemplate() && oSettingsDto.getUploadFileTemplate().equals("Inventory Target Data")){
                    settingsDao.updateInventoryTargetData(conn, strArr);
                }else if(null != oSettingsDto.getUploadFileTemplate() && oSettingsDto.getUploadFileTemplate().equals("Current Inventory Data")){
                    settingsDao.updateCurrentInventoryData(conn, strArr);
                }

                buffer.clear(); // do something with the data and clear/compact it.
                long endTime = System.currentTimeMillis();
                System.out.println("startTime :"+startTime);
                System.out.println("endTime :"+endTime);

            }
        }catch(Exception e){
        //e.printStackTrace();
        fc.close();
        raf.close();
        file.deleteOnExit();
    }


    return objSettingsDto;
}

2 个答案:

答案 0 :(得分:1)

你是对的,问题是你每次都要重置过滤器。因此,您需要进行一些修改以解决您的问题(我将假设所有代码都在同一个类中):

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 ...
}

答案 1 :(得分:1)

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