collection-type DP变更时如何通知?

How can I be notified when collection-type DP is changed?

我的英语水平很差,因为我的母语不是英语。

我创建了一个在 TextBox 控件上工作的行为。 该行为有一个名为 Items 的集合类型 DP。

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,它有一个名为 HighlightItems 的集合类型 DP。

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 并将 MainWindowViewModel 的 HighlightItems(DP) 与 HighlightBehavior 的 Items(DP) 连接起来,如下代码。

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

综上所述,结构如下图

我原以为只要项目发生变化,就会调用 HighlightBehavior 的 ItemsChanged。 但是没有调用。

我想在 HighlightBehavior 的集合类型 DP(Items) 更改时收到通知。 我必须做什么才能达到这个目标?

感谢您的阅读。 我会等一个答案。

我相信您正在寻找的是ObservableCollection。这是一种特殊类型的集合,每当添加、删除、更改或移动项目时都会引发其 CollectionChanged 事件。

我推荐以下内容:

  1. 不要将 HighlightItems 声明为 List<TextStyle>,而是将其声明为 ObservableCollection<TextStyle>.

  2. HighlightBehavior中再增加一个方法来处理CollectionChanged,例如:
    HighlightItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

  3. 只要设置 HighlightItems,就会调用您当前的 ItemsChanged 实现。使用它将事件处理程序附加到 CollectionChanged,如下所示:

var col = (ObservableCollection<TextStyle>)e.NewValue;
if (col != null) { col.CollectionChanged += HighlightItemsCollectionChanged; }
  1. 如果 HighlightItems 设置为 move than once,请不要忘记将任何现有的事件处理程序删除到先前的集合中。您可以将其与之前的代码片段一起添加到 ItemsChanged
col = (ObservableCollection<TextStyle>)e.OldValue;
if (col != null) { col.CollectionChanged -= HighlightItemsCollectionChanged; }
  1. HighlightItemsCollectionChanged 现在将在 HighlightItems 添加或删除项目时被调用。在这个方法中做任何你需要做的事情,或者如果你希望代码也 运行 当集合本身被替换时,你可以创建另一个方法来实际做你想做的事情,然后从两个 ItemsChangedHighlightItemsCollectionChanged.

谢谢。 我已经按照您的建议更改了代码,现在我可以在集合元素更改时收到通知。

我知道 ObservableCollection,但我不知道如何正确使用 CollectionChanged 事件。

事实上,之前我尝试使用 ObservableCollection 并在 Constructer 中注册了 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.
}

现在,我已经在 PropertyChangedCallback 方法中注册了 CollectionChanged 委托方法,如下所示,并调用了它(以下代码中的 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>());
}

感谢您的详细回答。