从绑定源筛选ListView项

本文关键字:ListView 筛选 绑定 | 更新日期: 2023-09-27 18:00:58

我的应用程序显示了一个ListView,它使用数据绑定来显示几个项目的列表。一些变量使用TwoWay绑定,因此更改保存在作为数据上下文的视图模型实例中。这是视图模型的"主要"实例,因为它包含所有项目。

现在我想过滤这个列表(包含所有项目(,只显示一部分项目。在过去,我在代码后面创建了一个新的视图模型实例,并将我想显示的所有项目从我的主实例复制到新创建的视图模型的实例中,然后将这个新视图模型设置为DataContext。

这很好,但当我更改Data时,它只会保存到新创建的实例,而不会保存到主实例。因此,当我更改过滤器时,项目将再次从主实例加载,其间没有任何更改。

有什么方法可以过滤视图模型的主要实例吗?我想处理主实例,以便自动保存更改。

ViewModel包含我自己类的ObservableCollection,我只想根据过滤器显示一些要绑定的项。

从绑定源筛选ListView项

在过去,我在代码后面创建了一个新的视图模型实例,并将我想显示的所有项目从我的主实例复制到新创建的视图模型的实例中,然后将这个新视图模型设置为DataContext。

我认为没有必要创建新的实例,您可以直接操作ObservableCollection作为ListView的源。

例如,我创建了一个包含所有数据的List,并将数据从该List:添加到ObservableCollection

<Page.DataContext>
    <local:MainPageViewModel x:Name="VM" />
</Page.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="4*" />
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ListView ItemsSource="{x:Bind VM.peopleCollection}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBox Text="{Binding Name, Mode=TwoWay}" />
                    <TextBox Text="{Binding Company, Mode=TwoWay}" />
                    <TextBox Text="{Binding Age, Mode=TwoWay}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <StackPanel Grid.Row="1">
        <Button Content="Age From 20-29" Click="{x:Bind VM.Age_Filter}" />
        <Button Content="Company AA" Click="{x:Bind VM.Company_Filter}" Margin="0,10" />
        <Button Content="Name Peter" Click="{x:Bind VM.Name_Filter}" />
    </StackPanel>
    <Button Content="Show All" Click="{x:Bind VM.Show_All}" Grid.Row="2" />
</Grid>

MainPageViewModel:中的代码隐藏

public class MainPageViewModel
{
    public MainPageViewModel()
    {
        peopleList.Add(new Person { Name = "Jay", Company = "AA", Age = 25 });
        peopleList.Add(new Person { Name = "Peter", Company = "BB", Age = 35 });
        peopleList.Add(new Person { Name = "Jayden", Company = "AA", Age = 27 });
        peopleList.Add(new Person { Name = "John", Company = "AAC", Age = 26 });
        peopleList.Add(new Person { Name = "Alan", Company = "BB", Age = 45 });
        peopleList.Add(new Person { Name = "Frank", Company = "BB", Age = 29 });
        peopleList.Add(new Person { Name = "Ami", Company = "AA", Age = 24 });
        peopleList.Add(new Person { Name = "Elvis", Company = "AA", Age = 30 });
        peopleCollection.Clear();
        foreach (var person in peopleList)
        {
            peopleCollection.Add(person);
        }
    }
    private static List<Person> peopleList = new List<Person>();
    public ObservableCollection<Person> peopleCollection = new ObservableCollection<Person>();
    public void Age_Filter(object sender, RoutedEventArgs e)
    {
        foreach (var person in peopleList)
        {
            if (person.Age > 29 || person.Age < 20)
                peopleCollection.Remove(person);
        }
    }
    public void Company_Filter(object sender, RoutedEventArgs e)
    {
        foreach (var person in peopleList)
        {
            if (person.Company != "AA")
                peopleCollection.Remove(person);
        }
    }
    public void Name_Filter(object sender, RoutedEventArgs e)
    {
        foreach (var person in peopleList)
        {
            if (person.Name != "Peter")
                peopleCollection.Remove(person);
        }
    }
    public void Show_All(object sender, RoutedEventArgs e)
    {
        peopleCollection.Clear();
        foreach (var person in peopleList)
        {
            peopleCollection.Add(person);
        }
    }
}

Person类的数据模型中,只有三个属性:Name、Company和Age。

public class Person : INotifyPropertyChanged
{
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            if (value != _Name)
            {
                _Name = value;
                OnPropertyChanged();
            }
        }
    }
    private string _Company;
    public string Company
    {
        get { return _Company; }
        set
        {
            if (value != _Company)
            {
                _Company = value;
                OnPropertyChanged();
            }
        }
    }
    private int _Age;
    public int Age
    {
        get { return _Age; }
        set
        {
            if (value != _Age)
            {
                _Age = value;
                OnPropertyChanged();
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

正如你所看到的,我在过滤时从ObservableCollection中删除了该项目,这将使过滤基于最后的过滤结果。如果你想根据所有项目进行过滤,你可以例如这样编码:

public void Company_Filter(object sender, RoutedEventArgs e)
{
    peopleCollection.Clear();
    foreach (var person in peopleList)
    {
        if (person.Company == "AA")
            peopleCollection.Add(person);
    }
}

通常是这样做的:

ICollectionView dataView =
              CollectionViewSource.GetDefaultView(IncList.ItemsSource);
dataView.Filter = o =>
                {
                    EventData t = o as EventData;
                    return t.action == evGroup.action && t.objid == evGroup.objid;
                };
dataView.Refresh();

这种技术对ListView进行过滤操作,而不是对ItemSource进行过滤操作。它很方便:您只需像往常一样使用数据源(添加删除元素(,ListView就会显示当前已过滤的视图。