WPF,为什么将PropertyChanged 添加到List<> 没有生效?

WPF, why adding PropertyChanged to List<> does not take into effect?

为什么 PropertyChangedEvent 可以添加到 String 属性,但不能添加到 List<> 属性?

xaml 喜欢这个:

<StackPanel>
    <ListBox ItemsSource="{Binding Items}" Height="300"/>
    <Button Click="Button_Click">Change</Button>
</StackPanel>

和 xaml.cs 这样的:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    //public ObservableCollection<String> Items { get; set; } = new ObservableCollection<String>(); // ok
    public List<String> Items  // no effect
    {
        get { return _items; }
        set
        {
            _items = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Items"));
        }
    }
    private List<String> _items = new List<string>();

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        Items.Add("aaa");
        Items.Add("bbb");
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Items.Clear();
        for (int i = 0; i < 5; i++)
            Items.Add(i.ToString());
     }
}

您的问题可以通过多种方式解决,

  1. 点击按钮创建另一个列表,示例代码如下

  2. 使用 Observable 集合

    改变
        private RelayCommand _buttonClick;
         public RelayCommand ButtonClick => _buttonClick ?? new RelayCommand(onButtonClick, canButtonClick);
    
     private bool canButtonClick(object obj)
     {
         return true;
     }
    
     private void onButtonClick(object obj)
     {
         List<String> tempItems = new List<string>();
         for (int i = 0; i < 5; i++)
             tempItems.Add(i.ToString());
         Items = tempItems;
     }
    

它不起作用,因为您只在设置整个列表时通知,而不是在列表中添加或删除项目时通知。

使用 ObservableCollection<string> 而不是 List<string>:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<string> _Items = new ObservableCollection<string>();
    public ObservableCollection<string> Items
    {
        get { return _Items; }
        set
        {
            _Items = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Items));
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        Items.Add("aaa");
        Items.Add("bbb");
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Items.Clear();
        for (int i = 0; i < 5; i++)
            Items.Add(i.ToString());
     }
}