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

Time:10-06

why PropertyChangedEvent can be add to a String property, but cannot be add to a List<> property?

the xaml likes this:

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

and the xaml.cs like this:

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());
     }
}

because stackoverflow prevents me from submitting the post, said you should first add some nonsense to dilute codes, then you can be allowed to submit the post:)

CodePudding user response:

Your issue can be fixed in multiple ways,

  1. Create another List on Button Click, sample code given below

  2. Use Observable Collection

    Change
        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;
     }
    

CodePudding user response:

It doesn't work because you're only notifying when the entire List is set, not when items are added or removed within the list.

Use an ObservableCollection<string> instead of 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());
     }
}
  • Related