WPF ListView使用INotifyPropertyChanged自动更新

6yt4nkrj  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(101)

我有一个名为ChosenListView的ListView在我的UserControl。在我的UserControl的构造函数中,我将DataContext设置为ViewModel,它包括一个ObservableCollection(称为Elements),其中包含具有bool IsChosen属性的元素。
我想让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;
}

这是我的ViewModel:

private class ViewModel
{
    public ObservableCollection<ChoosableElement> Elements { get; set; }
}

在我的UserControl的构造函数中,我将DataContext设置为ViewModel的一个新示例,并基于我的数据库初始化Elements,其中所有元素都以IsChosen=false开头。
My 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));
    }
}
5vf7fwbs

5vf7fwbs1#

每次设置IsChosen属性时,都需要刷新CollectionViewSource以调用Filter事件处理程序。
您也可以通过处理UserControl的代码隐藏中所有项的PropertyChanged事件,以编程方式自己完成此操作。大概是这样的:

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>

相关问题