Как отследить изменение значения поля типа «ObservableCollection»? - PullRequest
0 голосов
/ 25 января 2020

Как отследить изменение значения поля типа "ObservableCollection"?

Я написал пример, в котором я делаю расчет количества изменений полей, имеющих привязку. В этом примере я получаю сумму изменения поля «Str», но не могу получить сумму изменения поля «Arr».

MyClass.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace BindingArrayItem
{
    public class MyClass : INotifyPropertyChanged
    {
        private int changeCount;
        public int ChangeCount
        {
            get
            {
                return changeCount;
            }
            set
            {
                changeCount = value;
                OnPropertyChanged("ChangeCount");
            }
        }

        private String str;
        public String  Str
        {
            get
            {
                return str;
            }
            set
            {
                str = value;
                OnPropertyChanged("Str");
                AddCount(); // In this place the function is triggered 
            }
        }

        private ObservableCollection<String> arr = new ObservableCollection<String>();
        public ObservableCollection<String> Arr
        {
            get
            {
                return arr;
            }
            set
            {
                arr = value;
                AddCount(); // At this point, the function does not work (and no exception) !!!
            }
        }

        public MyClass()
        {
            ChangeCount = 0;

            Arr = new ObservableCollection<String>();
            Arr.Add("111");
            Arr.Add("222");

            Str = "333";
        }

        private void AddCount()
        {
            ChangeCount++;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string info)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}

MainWindow.xaml.cs

using System.Windows;

namespace BindingArrayItem
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MyClass myClass = null;

        public MainWindow()
        {
            InitializeComponent();

            myClass = new MyClass();
            this.label1.DataContext = myClass;
            this.label2.DataContext = myClass;
            this.label3.DataContext = myClass;
            this.label4.DataContext = myClass;
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            myClass.Str = "333";
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            myClass.Arr[1] = "333";
        }
    }
}

MainWindow.xaml

<Window x:Class="BindingArrayItem.MainWindow"
        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:local="clr-namespace:BindingArrayItem"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Label Name="label1" Content="{Binding Arr[0]}" HorizontalAlignment="Left" Margin="40,40,0,0" VerticalAlignment="Top"/>
        <Label Name="label2" Content="{Binding Arr[1]}" HorizontalAlignment="Left" Margin="40,80,0,0" VerticalAlignment="Top"/>
        <Label Name="label3" Content="{Binding Str}" HorizontalAlignment="Left" Margin="40,120,0,0" VerticalAlignment="Top"/>
        <Label Name="label4" Content="{Binding ChangeCount}" HorizontalAlignment="Left" Margin="40,160,0,0" VerticalAlignment="Top"/>
        <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="78,227,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
        <Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="207,227,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
    </Grid>
</Window>

1 Ответ

1 голос
/ 25 января 2020

Установщик свойства Arr вызывается только при назначении значения свойству с помощью

Arr = someValue;

, а не при доступе к объекту коллекции, например с помощью

Arr[i] = someValue;

. Вы однако может подписаться на событие CollectionChanged коллекции:

private ObservableCollection<string> arr = new ObservableCollection<string>();

public ObservableCollection<string> Arr
{
    get => arr;
    set
    {
        if (arr != null) arr.CollectionChanged -= ArrCollectionChanged;
        arr = value;
        if (arr != null) arr.CollectionChanged += ArrCollectionChanged;
    }
}

private void ArrCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    AddCount();
}
...