Как я могу получать уведомления об изменении DP типа коллекции?

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

Я создал следующее поведение, которое работает с элементом управления TextBox. Поведение имеет DP типа коллекции с именем Items.

class HighlightBehavior : Behavior<TextBox>
{

public List<TextStyle>Items
{
    get { return (List<TextStyle>)GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register("Items", typeof(List<TextStyle>), typeof(HighlightBehavior), new PropertyMetadata(ItemsChanged));

private static void ItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
   // break point 
}

}

И... Я создал MainWindow для использования в качестве следующего кода выше.

<MainWindow>
  <TextBox>
    <i:interaction.Behaviors>
      <behavior:HighlightBehavior/>
    </i:interaction.Behavior>
  </TextBox>
</MainWindow>

И я написал MainWindowViewModel с DP типа коллекции с именем HighlightItems.

class MainWindowViewModel : ViewModelBase
{
    public List<TextStyle> HighlightItems
    {
        get { return (List<TextStyle>)GetValue(HighlightItemsProperty ); }
        set { SetValue(HighlightItemsProperty , value); }
    }

    public static readonly DependencyProperty HighlightItemsProperty =
        DependencyProperty.Register("HighlightItems", typeof(List<TextStyle>), typeof(HighlightBehavior), new PropertyMetadata(null));

    public MainWindowViewModel()
    {
        SetValue(HighlightItemsProperty, new List<TextStyle>());
    }
}

И я привязал MainWindowViewModel к MainWindow и соединил HighlightItems(DP) MainWindowViewModel с Items(DP) HighlightBehavior в виде следующего кода.

<MainWindow>
  <TextBox>
    <i:interaction.Behaviors>
      <behavior:HighlightBehavior Items="{Binding HighlightItems, Mode=TwoWay}"/>
    </i:interaction.Behavior>
  </TextBox>
</MainWindow>

Подводя итог, структура выглядит следующим образом.

введите здесь описание изображения

Я ожидал, что ItemsChanged из HighlightBehavior вызывается при каждом изменении Items. Но не называется.

Я хочу получать уведомления всякий раз, когда изменяется DP(Items) типа коллекции HighlightBehavior. Что я должен сделать, чтобы достичь этой цели?

Спасибо за чтение. Я подожду ответа.


person jjw    schedule 13.10.2019    source источник
comment
docs.microsoft.com/en- нас/dotnet/api/ ?   -  person aybe    schedule 13.10.2019
comment
В вашем XAML у вас есть Items="{Binding HighlightBehavior}". Это опечатка? Я ожидаю, что это будет Items="{Binding HighlightItems}".   -  person Keithernet    schedule 14.10.2019
comment
Да Items={Привязка HighlightItems}. Это правильно.   -  person jjw    schedule 14.10.2019
comment
docs.microsoft.com/en-us/dotnet/api/… Только что я следовал инструкциям на сайте выше, но все равно не получаю уведомления, когда Items(DP of HighlightBehavior) изменяется.   -  person jjw    schedule 14.10.2019
comment
Вы хотите получать уведомления при замене всей коллекции (т. е. при установке DP) или при добавлении/удалении элемента из коллекции?   -  person Keith Stein    schedule 14.10.2019
comment
Я понятия не имею, что произойдет, если вы просто дадите ему сигнатуру метода, такую ​​​​как ваш код. Я бы всегда явно использовал новый метод PropertyChangedCallback (метод). Вместо новых PropertyMetadata (ItemsChanged). Это может решить вашу проблему, но все, что вам скажет, это когда все свойство установлено. Не вносит изменения в коллекцию.   -  person Andy    schedule 14.10.2019
comment
Вы хотите получать уведомления при замене всей коллекции (т. е. при установке DP) или при добавлении/удалении элемента из коллекции? -> Да, я хочу это.   -  person jjw    schedule 14.10.2019
comment
Какой вы хотите? Уведомление при замене всей коллекции или уведомление при добавлении/удалении элемента из коллекции? (Или оба?).   -  person Keith Stein    schedule 14.10.2019
comment
Уведомление о добавлении/удалении предмета из коллекции больше подходит для меня, но если возможно, я хочу знать оба случая.   -  person jjw    schedule 14.10.2019


Ответы (2)


Я считаю, что вы ищете ObservableCollection. Это особый тип коллекции, который вызывает событие CollectionChanged всякий раз, когда элемент добавляется, удаляется, изменяется или перемещается.

Я рекомендую следующее:

  1. Вместо объявления HighlightItems как List<TextStyle> объявите его как ObservableCollection<TextStyle>.

  2. Добавьте еще один метод в HighlightBehavior для обработки CollectionChanged, например:
    HighlightItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

  3. Ваша текущая реализация ItemsChanged будет вызываться всякий раз, когда установлено HighlightItems. Используйте это, чтобы прикрепить обработчик событий к CollectionChanged следующим образом:

var col = (ObservableCollection<TextStyle>)e.NewValue;
if (col != null) { col.CollectionChanged += HighlightItemsCollectionChanged; }
  1. Не забудьте удалить любой существующий обработчик событий из предыдущей коллекции, если HighlightItems задано перемещение более одного раза. Вы можете добавить это в ItemsChanged вместе с предыдущим фрагментом:
col = (ObservableCollection<TextStyle>)e.OldValue;
if (col != null) { col.CollectionChanged -= HighlightItemsCollectionChanged; }
  1. HighlightItemsCollectionChanged теперь будет вызываться всякий раз, когда элемент добавляется или удаляется из HighlightItems. Делайте все, что вам нужно, в этом методе, или, если вы хотите, чтобы код также запускался при замене самой коллекции, вы можете создать другой метод, который на самом деле делает то, что вы хотите, а затем вызывать этот метод как из ItemsChanged, так и из HighlightItemsCollectionChanged.
person Keith Stein    schedule 14.10.2019
comment
Спасибо. Я изменил код по вашему совету, и теперь я могу получать уведомления при изменении элемента коллекции. - person jjw; 14.10.2019

Спасибо. Я изменил код по вашему совету, и теперь я могу получать уведомления при изменении элемента коллекции.

Я знал о ObservableCollection, но не знал, как правильно использовать событие CollectionChanged.

Фактически, ранее я пытался использовать ObservableCollection и зарегистрировал метод делегата CollectionChanged в конструкторе следующим образом, но он не вызывается.

public ObservableCollection<TextStyle> Items
{
    get { return (ObservableCollection<TextStyle>)GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

// Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register("Items", typeof(ObservableCollection<TextStyle>), typeof(HighlightBehavior),
          new PropertyMetaData(null));

public HighlightBehavior()
{
    SetValue(ItemsProperty, new ObservableCollection<TextStyle>());
    Items.CollectionChanged += OnCollectionChanged;
}

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // The code when the collection is changed.
}

Теперь я зарегистрировал метод делегата CollectionChanged в методе PropertyChangedCallback следующим образом, и он (метод OnCollectionChanged в следующем коде) вызывается.

public ObservableCollection<TextStyle> Items
{
    get { return (ObservableCollection<TextStyle>)GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

// Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register("Items", typeof(ObservableCollection<TextStyle>), typeof(HighlightBehavior),
          new PropertyMetaData(ItemsChanged));

private static void ItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var col = (ObservableCollection<TextStyle>)e.NewValue;
    if (col != null) { col.CollectionChanged += OnCollectionChanged; ; }

    col = (ObservableCollection<TextStyle>)e.OldValue;
    if (col != null) { col.CollectionChanged -= OnCollectionChanged; }
}

public HighlightBehavior()
{
    SetValue(ItemsProperty, new ObservableCollection<TextStyle>());
}

Спасибо за подробный ответ.

person jjw    schedule 14.10.2019