我有一个看似相当容易的问题,但似乎我遇到了问题:
我有一个包含一些数据的数据网格:
<DataGrid ItemsSource="{Binding Candidates, IsAsync=True}"
AutoGenerateColumns="False"
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
VirtualizingStackPanel.IsVirtualizing="True"
CanUserAddRows="false">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Firstname}" Header="Imię" />
<DataGridTextColumn Binding="{Binding Lastname}" Header="Nazwisko" />
<DataGridTextColumn Binding="{Binding commendation.Name}" Header="Polecenie" />
</DataGrid.Columns>
</DataGrid>
现在使用mvvm和命令我在这些上应用了一些过滤器,它看起来像:
public CatalogViewModel()
{
this._catalog = new CatalogContexct();
this._candidates = this._catalog.Candidates.Include("commendation").ToList();
var candidates = new ListCollectionView(this._candidates);
this.Candidates = CollectionViewSource.GetDefaultView(candidates);
this.FirstameCommand = new RelyCommand(FilterFirstname, param => this._canExecute);
this.LastnameCommand = new RelyCommand(FilterLastname, param => this._canExecute);
this.CommendationCommand = new RelyCommand(FilterCommendation, param => this._canExecute);
}
过滤器看起来像:
public void FilterFirstname(object obj)
{
this.Candidates.Filter += item =>
{
Candidate candidate = item as Candidate;
return candidate.Firstname.Contains(obj.ToString());
};
this.Candidates.Refresh();
}
public void FilterLastname(object obj)
{
this.Candidates.Filter += item =>
{
Candidate candidate = item as Candidate;
if(string.IsNullOrWhiteSpace(candidate.Lastname))
{
return false;
}
return candidate.Lastname.Contains(obj.ToString());
};
this.Candidates.Refresh();
}
public void FilterCommendation(object obj)
{
this.Candidates.Filter += item =>
{
Candidate candidate = item as Candidate;
if (string.IsNullOrWhiteSpace(candidate.commendation.Name))
{
return false;
}
return candidate.commendation.Name.Contains(obj.ToString());
};
this.Candidates.Refresh();
}
现在这基本上按预期工作但是它分别对每个列起作用,所以如果我输入名称它将过滤我的名字,如果我输入姓氏,它将过滤我的姓氏,但它将覆盖名称,所以我不会得到确切的匹配名称和姓氏,我想汇总这些过滤器。
有没有办法聚合过滤器?
答案 0 :(得分:3)
为什么不起作用?
在每个FilterCommendation
,FilterLastname
,FilterFirstname
上,您要向this.Candidates.Filter
添加另一个代理。所有这些都将在Refresh
上执行,但只返回最后一个委托的结果。请考虑以下示例:
Predicate<int> tmp = i => true;
tmp += i => i != 0;
Assert.AreEqual(true, tmp(1));
Assert.AreEqual(false, tmp(0));
它将始终返回i != 0
,因为它是最后一个谓词,但所有这些都将被执行。他们之间没有'和'。
如何实现目标?
您可以创建过滤器集合并在其中添加或删除过滤器并刷新视图。完整示例如下:
Dictionary<string, Predicate<Candidate>> filters
= new Dictionary<string, Predicate<Candidate>>();
public CatalogViewModel()
{
...
Candidates.Filter = FilterCandidates;
}
private bool FilterCandidates(object obj)
{
Candidate c = (Candidate)obj;
return filters.Values
.Aggregate(true,
(prevValue, predicate) => prevValue && predicate(c));
}
public void FilterFirstname(object obj)
{
string val = obj.ToString();
AddFilterAndRefresh(
"FirstName",
candidate => candidate.Firstname.Contains(val));
}
public void FilterLastname(object obj)
{
string val = obj.ToString();
AddFilterAndRefresh(
"FirstName",
candidate => !string.IsNullOrWhiteSpace(candidate.Lastname) && candidate.Lastname.Contains(val));
}
public void ClearFilters()
{
filters.Clear();
Candidates.Refresh();
}
public void RemoveFilter(string filterName)
{
if (filters.Remove(filterName))
{
Candidates.Refresh();
}
}
private void AddFilterAndRefresh(string name, Predicate<Candidate> predicate)
{
filters.Add(name, predicate);
Candidates.Refresh();
}