WPF, не работает с PropertyChanged для Properties.Настройки (StringCollection) в ListView

#c# #wpf #mvvm #data-binding

#c# #wpf #mvvm #привязка данных

Вопрос:

Я пытаюсь установить содержимое для ListView из Properties .Настройки (StringCollection). Завершение установлено успешно, но если я удаляю элемент, ListView не обновляется. Если я закрою и открою SettingWindow, содержимое внутри ListView будет правильным. Это означает, что что-то не так в привязке данных, вероятно, не работает с PropertyChanged.

SettingWindow.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>
  

SettingWindow.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 amp;amp; obj != null));
            }
        }
    }
}
  

Комментарии:

1. Если вы имели в виду, что удаляете строку списка, то вам нужно иметь ObservableCollection, который запускает события CollectionChanged, а не PropertyChanged

2. вы также можете использовать функцию обновления из CollectionViewSource?

3. Нет, вы не можете обновлять привязки подобным образом. Вы указываете другой источник. Простой обходной путь — создать свойство только для получения, в SettingWindowViewModel котором будет перенаправляться Properties.Settings.Genres и использовать его в привязках. Затем вы можете вызвать уведомление об этом в command.

4. Как примечание, настройка UpdateSourceTrigger=PropertyChanged привязки ItemsSource бессмысленна. Это влияет только на привязки TwoWay или OneWayToSource.

5. @Sinatr, я должен создать метод внутри SettingWindowViewModel , который будет: 1) Получать элементы из Properties.Settings.Genres to ObservableCollection 2) Подключать ListView ObservableCollection и что-то делать 3) Конвертировать ObservableCollection обратно в Properties.Settings.Genres ?

Ответ №1:

Вместо привязки к какому-либо другому свойству в каком-либо другом источнике вы можете использовать возможности ViewModel, которая используется для работы между view и models .

Добавьте следующее свойство в ViewModel

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

и привязать к нему

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

Теперь внутри различных команд вы должны иметь возможность указывать привязки для обновления

 OnPropertyChanged(nameof(Genres));