我的 UserControl 中有一个名为 ChosenListView 的 ListView。在我的 UserControl 的构造函数中,我将 DataContext 设置为我的 ViewModel,其中包括具有 bool IsChosen 属性的元素的 ObservableCollection(称为 Elements)。
我想让我的ChosenListView显示Elements中IsChosen属性为true的所有元素。我希望每次更改其中一个元素 IsChosen 属性时它都会自动更新。
我尝试利用 INotifyPropertyChanged,但我似乎无法让它工作,希望得到任何帮助。
我在这里定义了一个CollectionViewSource:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<CollectionViewSource
x:Key="ChosenElementsViewSource"
x:Name="ChosenElementsViewSource"
Source="{Binding Elements}"
Filter="ChosenElementsViewSource_Filter"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
这是过滤器:
private void ChosenElementsViewSource_Filter(object sender, FilterEventArgs e)
{
e.Accepted = e.Item is ChoosableElement choosableElement &&
choosableElement.IsChosen;
}
这是我的视图模型:
private class ViewModel
{
public ObservableCollection<ChoosableElement> Elements { get; set; }
}
在我的 UserControl 的构造函数中,我将 DataContext 设置为 ViewModel 的新实例,并根据我的数据库初始化元素,其中所有元素都以 IsChosen=false 开头。
我的 ListView 在 XAML 中定义了 ItemsSource:
ItemsSource="{Binding Source={StaticResource ChosenElementsViewSource}}"
最后,我的ChoosableElement定义如下:
private class ChoosableElement : INotifyPropertyChanged
{
public Element Element { get; set; }
private bool isChosen = false;
public bool IsChosen
{
get { return isChosen; }
set
{
if (isChosen != value)
{
isChosen = value;
OnPropertyChanged(nameof(IsChosen));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
每次设置
CollectionViewSource
属性时,您都需要刷新 Filter
来调用 IsChosen
事件处理程序。
您可以通过处理
PropertyChanged
代码隐藏中所有项目的 UserControl
事件,以编程方式自行执行此操作。像这样的东西:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
var viewModel = new ViewModel();
DataContext = viewModel;
if (viewModel.Elements != null)
{
viewModel.Elements.CollectionChanged += OnCollectionChanged;
foreach (object item in viewModel.Elements)
(item as INotifyPropertyChanged).PropertyChanged
+= new PropertyChangedEventHandler(OnPropertyChanged);
}
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (object item in e.NewItems)
(item as INotifyPropertyChanged).PropertyChanged
+= new PropertyChangedEventHandler(OnPropertyChanged);
if (e.OldItems != null)
foreach (object item in e.OldItems)
(item as INotifyPropertyChanged).PropertyChanged
-= new PropertyChangedEventHandler(OnPropertyChanged);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ChoosableElement.IsChosen))
{
(Resources["ChosenElementsViewSource"] as CollectionViewSource)?
.View.Refresh();
}
}
private void ChosenElementsViewSource_Filter(object sender, FilterEventArgs e)
{
e.Accepted = e.Item is ChoosableElement choosableElement &&
choosableElement.IsChosen;
}
...
}
或者您可以直接在 XAML 标记中的
CollectionViewSource
上启用 .NET Framework 4.5 中引入的实时过滤功能:
<CollectionViewSource
x:Key="ChosenElementsViewSource"
x:Name="ChosenElementsViewSource"
Source="{Binding Elements}"
Filter="ChosenElementsViewSource_Filter"
IsLiveFilteringRequested="True"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<CollectionViewSource.LiveFilteringProperties>
<system:String>IsChosen</system:String>
</CollectionViewSource.LiveFilteringProperties>
</CollectionViewSource>