我目前有一个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的过滤器时,会出现问题。例如,用户想要过滤公司类型,因此他们会选择currentCheckBox
,supplierCheckBox
和subbieCheckBox
。这将返回所有当前也是分包商的供应商。
这仍然会返回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;
}
答案 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