В C # как вызвать событие PropertyChanged, когда изменяются элементы в массиве - PullRequest
0 голосов
/ 18 января 2019

У меня есть свойство массива, в которое я хочу уведомлять всякий раз, когда изменяются какие-либо элементы этого массива.

private double[] _OffsetAngles = new double[3];
public double[] OffsetAngles
    {
        get { return _OffsetAngles; }
        set
        {
            _OffsetAngles = value;
            NotifyPropertyChanged();
        }
    }

Если какой-либо из элементов OffsetAngles изменяется, я хочу получить уведомление. т.е. если я установил OffsetAngles [1] = 20; // Триггер должен произойти. если я установлю OffsetAngles [0] = 40; // Запуск должен произойти снова.

Ответы [ 4 ]

0 голосов
/ 18 января 2019

Итак, как уже упоминали другие, в вашем случае вы запускаете NotifyPropertyChanged (), когда изменяется сам массив, а не какой-либо элемент массива.

Если вы хотите, чтобы элементы могли вызывать событие, вам нужно реализовать класс, подобный:

public class NotifyingData<T> : INotifyPropertyChanged 
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private T _Data;
    public T Data
    {
        get { return _Data; }
        set { _Data = value; NotifyPropertyChanged(); }
    }
}

и затем заполните ваш массив этим классом:

_OffsetAngles[0] = new NotifyingData<double> { Data = 10 };

У меня сейчас нет доступа к VS, поэтому могут быть некоторые ошибки, но это должно быть правильным для вас понятием.

0 голосов
/ 18 января 2019

Представьте, что вы используете не двойной, а какой-то класс. И затем, что поле этого класса изменилось. Должен ли массив поднять свойство изменено? Конечно, нет. Таким образом, есть несколько решений, которые вы можете рассмотреть:

  • использование ObservableCollection и его SetItem метод
  • используйте ObservableCollection и вместо назначения значения удалите и вставьте значение
  • вместо двойного использования некоторого класса, который реализует INotifyPropertyChanged, и когда изменения в dobule вызывают это событие, подход должен быть правильным, если целью является привязка данных
  • каждый раз воссоздайте Array (громоздко и неэффективно, но все еще работает)
0 голосов
/ 18 января 2019

У меня была такая же проблема некоторое время назад. Мне приходилось обновлять DataTable всякий раз, когда данные менялись, и вот как я решил это в своей программе:

public ObservableCollection<KeyStroke> keyList = new ObservableCollection<KeyStroke>();
public class KeyStroke : INotifyPropertyChanged
{
    // KeyStroke class storing data about each key and how many types it received
    private int id;
    private int numPress;
    public KeyStroke(int id, int numPress)
    {
        Id = id;
        NumPress = numPress;
    }
    public int Id
    {
        get => id;
        set
        {
            id = value;
            NotifyPropertyChanged("Id");
        }
    }
    public int NumPress
    {
        get { return this.numPress; }
        set
        {
            this.numPress = value;
            NotifyPropertyChanged("NumPress");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged; //This handle the propertyChanged
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); //This is the WPF code for the DataGrid but you can replace it by whatever you need
    }
}

Это должно вам помочь. Вы также можете поместить условия в getter / setters свойств, но я думаю, что это не очень красиво

0 голосов
/ 18 января 2019

В этом примере показано, как создать и привязать коллекцию, производную от класса ObservableCollection, который является классом коллекции, который предоставляет уведомления при добавлении или удалении элементов.

public class NameList : ObservableCollection<PersonName>  
{  
    public NameList() : base()  
    {  
        Add(new PersonName("Willa", "Cather"));  
        Add(new PersonName("Isak", "Dinesen"));  
        Add(new PersonName("Victor", "Hugo"));  
        Add(new PersonName("Jules", "Verne"));  
    }  
  }  

  public class PersonName  
  {  
      private string firstName;  
      private string lastName;  

      public PersonName(string first, string last)  
      {  
          this.firstName = first;  
          this.lastName = last;  
      }  

      public string FirstName  
      {  
          get { return firstName; }  
          set { firstName = value; }  
      }  

      public string LastName  
      {  
          get { return lastName; }  
          set { lastName = value; }  
      }  
  } 

Объекты в вашей коллекции должны удовлетворять требованиям, описанным в Обзоре источников связывания. В частности, если вы используете OneWay или TwoWay (например, вы хотите, чтобы ваш пользовательский интерфейс обновлялся при динамическом изменении свойств источника), вы должны реализовать подходящий механизм уведомления об изменении свойств, такой как интерфейс INotifyPropertyChanged.

Ссылка: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-create-and-bind-to-an-observablecollection

...