gpt4 book ai didi

c# - WPF MVVM 如何在 ICollectionView 中组合多个过滤器

转载 作者:太空宇宙 更新时间:2023-11-03 23:04:53 25 4
gpt4 key购买 nike

我有一个看起来很简单的问题,但我似乎对它有疑问:

我有一个包含一些数据的数据网格:

            <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();
}

现在这基本上按预期工作但它分别在每一列上工作所以如果我输入名称它会过滤我的名字如果我输入姓氏它会过滤我的姓氏但它会覆盖名字所以我不会得到确切的匹配姓名和姓氏,我想聚合该过滤器。

有什么方法可以聚合这些过滤器吗?

最佳答案

为什么不起作用?

在每个 FilterCommendationFilterLastnameFilterFirstname 上,您都在向 this.Candidates.Filter 添加另一个委托(delegate)。所有这些都将在 Refresh 上执行,但只会返回最后一个委托(delegate)的结果。考虑以下示例:

Predicate<int> tmp = i => true;
tmp += i => i != 0;

Assert.AreEqual(true, tmp(1));
Assert.AreEqual(false, tmp(0));

它总是会返回 i != 0 因为它是最后一个谓词,但它们都会被执行。它们之间没有“和”。

如何实现目标?

您可以创建过滤器集合并从中添加或删除并刷新 View 。完整示例如下:

    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();
}

关于c# - WPF MVVM 如何在 ICollectionView 中组合多个过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41659878/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com