【问题标题】:WPF, doesn't work OnPropertyChanged for Properties.Settings (StringCollection) in listViewWPF,对于listView中的Properties.Settings(StringCollection)的OnPropertyChanged不起作用
【发布时间】:2020-11-09 10:49:10
【问题描述】:

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

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>

设置窗口.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();
        }
    }
}

SettingWindowViewModel.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));
            }
        }
    }
}

【问题讨论】:

  • 如果您的意思是要删除列表中的一行,那么您需要拥有触发 CollectionChanged 事件而不是 PropertyChanged 的​​ ObservableCollection
  • 你也可以使用 CollectionViewSource 的刷新功能吗?
  • 不,您不能像这样更新绑定。您正在指定不同的来源。简单的解决方法是在 SettingWindowViewModel 中创建 getter-only 属性,该属性将重定向到 Properties.Settings.Genres 并在绑定中使用它。然后你可以在命令中为它发出通知。
  • 请注意,在 ItemsSource Binding 上设置 UpdateSourceTrigger=PropertyChanged 是没有意义的。它仅在 TwoWay 或 OneWayToSource 绑定中有效。
  • @Sinatr,我必须在SettingWindowViewModel 中创建方法,这将是:1)从Properties.Settings.Genres 获取项目到ObservableCollection 2)将listView 与ObservableCollection 连接并做一些事情3)转换ObservableCollectionProperties.Settings.Genres ?

标签: c# wpf mvvm data-binding


【解决方案1】:

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

将以下属性添加到 ViewModel

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

并绑定到它

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

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

OnPropertyChanged(nameof(Genres));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 2018-02-20
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多