WPF ListView 使用 INotifyPropertyChanged 自动更新

问题描述 投票:0回答:1

我的 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));
    }
}
c# wpf listview inotifypropertychanged
1个回答
0
投票

每次设置

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>
© www.soinside.com 2019 - 2024. All rights reserved.