从绑定源过滤 ListView 项
Filter ListView Items from Binding Source
我的应用显示了一个 ListView,它使用数据绑定来显示包含多个项目的列表。一些变量使用双向绑定,因此更改保存在作为数据上下文的视图模型实例中。这是我的 "main" 视图模型实例,因为它包含所有项目。
现在我想过滤这个列表(包含所有项目)并且只显示部分项目。过去,我在后面的代码中创建了一个新的 viewmodel 实例,并将我想要显示的所有项目从我的主实例复制到新创建的 viewmodel 实例,然后将这个新的 viewmodel 设置为 DataContext。
这工作正常,但是当我更改数据时,它只会保存到新创建的实例而不是主实例。因此,当我更改过滤器时,项目将再次从主实例加载而不会在两者之间进行任何更改。
有什么方法可以过滤视图模型的主要实例吗?我想在主实例上工作,以便自动保存更改。
ViewModel 包含一个我自己的 ObservableCollection class,我只想根据过滤器显示一些要绑定的项目。
In the past, I created a new instance of the viewmodel in the code behind and copied all the items I wanted to show to from my main instance to the newly created instance of the viewmodel and then set this new viewmodel as the 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);
}
}
}
classPerson
的数据模型中只有三个属性:姓名、公司和年龄。
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 显示当前视图已过滤。
我的应用显示了一个 ListView,它使用数据绑定来显示包含多个项目的列表。一些变量使用双向绑定,因此更改保存在作为数据上下文的视图模型实例中。这是我的 "main" 视图模型实例,因为它包含所有项目。
现在我想过滤这个列表(包含所有项目)并且只显示部分项目。过去,我在后面的代码中创建了一个新的 viewmodel 实例,并将我想要显示的所有项目从我的主实例复制到新创建的 viewmodel 实例,然后将这个新的 viewmodel 设置为 DataContext。
这工作正常,但是当我更改数据时,它只会保存到新创建的实例而不是主实例。因此,当我更改过滤器时,项目将再次从主实例加载而不会在两者之间进行任何更改。
有什么方法可以过滤视图模型的主要实例吗?我想在主实例上工作,以便自动保存更改。
ViewModel 包含一个我自己的 ObservableCollection class,我只想根据过滤器显示一些要绑定的项目。
In the past, I created a new instance of the viewmodel in the code behind and copied all the items I wanted to show to from my main instance to the newly created instance of the viewmodel and then set this new viewmodel as the 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);
}
}
}
classPerson
的数据模型中只有三个属性:姓名、公司和年龄。
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 显示当前视图已过滤。