首页 > 解决方案 > WPF,对于 listView 中的 Properties.Settings (StringCollection) 的 OnPropertyChanged 不起作用

问题描述

我尝试从 Properties.Settings (StringCollection) 为 listView 设置内容。Contet 设置成功,但如果我删除项目,listView 不会刷新。如果我关闭并打开 SettingWindow,则 listView 中的内容是正确的。意思是,DataBinding 出了点问题,OnPropertyChanged 可能不起作用。

设置窗口.xaml:

<Window x:Class="FilmDbApp.Views.SettingWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:p="clr-namespace:FilmDbApp.Properties"
        xmlns:local="clr-namespace:FilmDbApp.Views"
        mc:Ignorable="d"
        Title="Setting" Height="500" Width="400" ResizeMode="NoResize" WindowStartupLocation="CenterOwner">
    <DockPanel>
        <TabControl>
            <TabItem Header="Genre options">
                <StackPanel>
                    <ListView ItemsSource="{Binding Source={x:Static p:Settings.Default}, Path=Genres, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedGenre}"" VerticalAlignment="Top"/>
                    <Button Command="{Binding DeleteGenreCommand}" CommandParameter="{Binding SelectedGenre}" Content="Delete"/>
                </StackPanel>
            </TabItem>
            <TabItem Header="Autosave options"/>
        </TabControl>
    </DockPanel>
</Window>

设置窗口.cs:

using System.Windows;
using FilmDbApp.ViewModels;

namespace FilmDbApp.Views
{
    /// <summary>
    /// Interaction logic for SettingWindow.xaml
    /// </summary>
    public partial class SettingWindow : Window
    {
        public SettingWindow()
        {
            InitializeComponent();

            DataContext = new SettingWindowViewModel();
        }
    }
}

设置WindowViewModel.cs:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using FilmDbApp.Views;
using FilmDbApp.Models;
using FilmDbApp.Utils;

namespace FilmDbApp.ViewModels
{
    class SettingWindowViewModel : INotifyPropertyChanged
    {
        private string selectedGenre;
        public string SelectedGenre
        {
            get { return selectedGenre; }

            set
            {
                selectedGenre = value;
                OnPropertyChanged("SelectedGenre");
            }
        }

        public SettingWindowViewModel()
        {

        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }

        // Delete genre
        private RelayCommand deleteGenreCommand;
        public RelayCommand DeleteGenreCommand
        {
            get
            {
                return deleteGenreCommand ??
                    (deleteGenreCommand = new RelayCommand(obj =>
                    {
                        string genre = obj as string;
                        Properties.Settings.Default.Genres.Remove(genre);
                        Properties.Settings.Default.Save();
                        OnPropertyChanged("Genres");
                    }, (obj) => Properties.Settings.Default.Genres.Count > 0 && obj != null));
            }
        }
    }
}

标签: c#wpfmvvmdata-binding

解决方案


您可以利用 ViewModel 的强大功能,而不是绑定到其他源中的其他属性,它用于在视图和模型之间工作。

将以下属性添加到 ViewModel

class SettingWindowViewModel : INotifyPropertyChanged
{
    public List<Genre> Genres => Properties.Settings.Default.Genres;
    ...
}

并绑定到它

<ListView ItemsSource="{Binding Genres}"
          SelectedItem="{Binding SelectedGenre}"... />

现在在各种命令中,您应该能够告诉绑定更新

OnPropertyChanged(nameof(Genres));

推荐阅读