使用 ICollectionView 过滤可观察集合
本文关键字:观察 集合 过滤 ICollectionView 使用 | 更新日期: 2023-09-27 17:57:08
我已经ObservableCollection
绑定到dataGrid
,现在我想过滤我看到的我需要使用的呈现数据ICollectionView
但我不确定如何使用我的MVVM
模式添加ICollectionView
。
我的简化代码如下所示:
public class MainViewModel : ViewModelBase , IBarcodeHandler
{
public ObservableCollection<TraceDataItem> TraceItemCollectionViewSource { get; set; }
}
我的 XAML
<Window xmlns:controls="clr-namespace:Mentor.Valor.vManage.RepairStation.Controls"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
<DataGrid Grid.Row="2" ColumnWidth="*" ItemsSource="{Binding TraceItemCollectionViewSource , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" RowStyle="{StaticResource TraceRowStyle}" IsReadOnly="True" Name="TraceDataGrid" Margin="5,5,5,5" Padding="5,5,5,5" AutoGenerateColumns="False">
</Window>
如何在此处添加ICollectionView
以便对视图应用过滤?
您需要:
public class MainViewModel : ViewModelBase, IBarcodeHandler
{
public ICollectionView TraceItemCollectionView
{
get { return CollectionViewSource.GetDefaultView(TraceItemCollectionViewSource); }
}
public ObservableCollection<TraceDataItem> TraceItemCollectionViewSource { get; set; }
}
然后,在代码中的某个地方(可能在构造函数中)添加过滤器:
TraceItemCollectionView.Filter = o =>
{
var item = (TraceDataItem) o;
//based on item, return true if it should be visible, or false if not
return true;
};
而且,在 XAML 中,您需要将绑定更改为 TraceItemCollectionView 属性。
您可以从命令调用 Filter 回调,并从 CollectionViewSource 公开 View 属性:
public class ViewModel: INotifyPropertyChanged
{
private CollectionViewSource data = new CollectionViewSource();
private ObservableCollection<Child> observableChilds = new ObservableCollection<Child>();
public ViewModel()
{
var model = new Model();
model.ChildList.Add(new Child { Name = "Child 1" });
model.ChildList.Add(new Child { Name = "Child 2" });
model.ChildList.Add(new Child { Name = "Child 3" });
model.ChildList.Add(new Child { Name = "Child 4" });
//Populate ObservableCollection
model.ChildList.ToList().ForEach(child => observableChilds.Add(child));
this.data.Source = observableChilds;
ApplyFilterCommand = new DelegateCommand(OnApplyFilterCommand);
}
public ICollectionView ChildCollection
{
get { return data.View; }
}
public DelegateCommand ApplyFilterCommand { get; set; }
private void OnApplyFilterCommand()
{
data.View.Filter = new Predicate<object>(x => ((Child)x).Name == "Child 1");
OnPropertyChanged("ChildCollection");
}
}
//Sample Model used
public class Model
{
public Model()
{
ChildList = new HashSet<Child>();
}
public ICollection<Child> ChildList { get; set; }
}
public class Child
{
public string Name { get; set; }
}
//View
<ListBox ItemsSource="{Binding Path = ChildCollection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Command="{Binding ApplyFilterCommand}"/>
CollectionView
并不总是最好的解决方案。 您还可以使用一些简单的 LinQ 来筛选集合。举这个简单的例子:
public ObservableCollection<TraceDataItem> FilteredData
{
get
{
return new ObservableCollection<TraceDataItem>(YourUnfilteredCollection.Where(
i => MeetsFilterRequirements(i)));
}
}
private bool MeetsFilterRequirements(TraceDataItem item)
{
return item.SomeProperty == someValue || item is SomeType;
}
这种方法的优点是您可以添加一些复杂的过滤要求。需要注意的一点是:每当此方法中的任何属性发生更改时,都需要调用 NotifyPropertyChanged("FilteredData")
以确保相应地更新 UI。