WPF:如何挂钩ListView的ItemsSource CollectionChanged通知?

时间:2021-03-15 23:56:08

I have a ListView that is databound to an ObservableCollection ...

我有一个数据绑定到ObservableCollection的ListView ...

<ListView x:Name="List1" ItemsSource="{Binding MyList}" />

I can't seem to find any event that are triggered when the collection changes, so I'm thinking that somehow I need to hook into the collectionchanged notification somehow? I'm not really sure how to do that.

我似乎无法找到任何在集合发生变化时触发的事件,所以我想某种程度上我需要以某种方式挂钩到collectionschanged通知中?我不确定该怎么做。

Basically, when the collection changes I want to do additional work beyond what the ListView already does in updating it's list.

基本上,当集合发生变化时,我想要做更多的工作,而不是ListView在更新它的列表时所做的工作。

3 个解决方案

#1


15  

By default the ItemsSource is of type IEnumerable. You need to first cast to a type that has access to the CollectionChanged event, then add a handler for that event.

默认情况下,ItemsSource的类型为IEnumerable。您需要首先强制转换为可以访问CollectionChanged事件的类型,然后为该事件添加处理程序。

((INotifyCollectionChanged)List1.ItemsSource).CollectionChanged +=
    new NotifyCollectionChangedEventHandler(List1CollectionChanged);

public void List1CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
{
    // Your logic here
}


Note: I cast it to INotifyCollectionChanged in my example, but you can really cast it to any object that implements that. Though, as a best practice, you should cast to the most generic type that gives you access to the methods/properties/events you need. So, while you can cast it to an ObservableCollection, you don't need to. INotifyCollectionChanged contains the event you need and if you ever decide to use some other type of collection that implements it, this will continue to work, whereas casting to an ObservableCollection means that if you one day decide that you're list is now of type MyOwnTypeOfObservableCollectionNotDerivedFromObservableCollection than this will break. ;)

P.S. This should go in the xaml code-behind.

附:这应该在xaml代码隐藏中。

#2


0  

you are going to have to attach the handler to your list. Or, use a CollectionView and hook the changed event there.

您将不得不将处理程序附加到列表中。或者,使用CollectionView并在此处挂接已更改的事件。

in your codebehind, do like this:

在你的代码隐藏中,这样做:

MyList.CollectionChanged += new NotifyCollectionChangedEventHandler( this.MyCollectionChanged );


private void SortCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
  Debug.WriteLine( "Changed" );
}

#3


0  

An ObservableCollection{T} exposes the INotifyCollectionChanged.CollectionChanged event. When binding to an ItemsSource the data binding engine handles the propogation of changes from the source to the items control, but if you need to perform additional processing you can attach a handler to the CollectionChanged event and use the NotifyCollectionChangedEventArgs it provides.

ObservableCollection {T}公开INotifyCollectionChanged.CollectionChanged事件。绑定到ItemsSource时,数据绑定引擎处理从源到项控件的更改传播,但是如果需要执行其他处理,可以将处理程序附加到CollectionChanged事件并使用它提供的NotifyCollectionChangedEventArgs。

Assuming you have a public property on your view model named MyList:

假设您的视图模型上有一个名为MyList的公共属性:

public ObservableCollection<T> MyList
{
  get
  {
    if(_viewModelMyList == null)
    {
      _viewModelMyList = new ObservableCollection<T>;
      _viewModelMyList.CollectionChanged += (o, e) => 
      {
        // code to process change event can go here
        if(e.Action == NotifyCollectionChangedAction.Add)
        {
        }
      };
    }
    return _viewModelMyList;
  }
}
private ObservableCollection<T> _viewModelMyList;

#1


15  

By default the ItemsSource is of type IEnumerable. You need to first cast to a type that has access to the CollectionChanged event, then add a handler for that event.

默认情况下,ItemsSource的类型为IEnumerable。您需要首先强制转换为可以访问CollectionChanged事件的类型,然后为该事件添加处理程序。

((INotifyCollectionChanged)List1.ItemsSource).CollectionChanged +=
    new NotifyCollectionChangedEventHandler(List1CollectionChanged);

public void List1CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
{
    // Your logic here
}


Note: I cast it to INotifyCollectionChanged in my example, but you can really cast it to any object that implements that. Though, as a best practice, you should cast to the most generic type that gives you access to the methods/properties/events you need. So, while you can cast it to an ObservableCollection, you don't need to. INotifyCollectionChanged contains the event you need and if you ever decide to use some other type of collection that implements it, this will continue to work, whereas casting to an ObservableCollection means that if you one day decide that you're list is now of type MyOwnTypeOfObservableCollectionNotDerivedFromObservableCollection than this will break. ;)

P.S. This should go in the xaml code-behind.

附:这应该在xaml代码隐藏中。

#2


0  

you are going to have to attach the handler to your list. Or, use a CollectionView and hook the changed event there.

您将不得不将处理程序附加到列表中。或者,使用CollectionView并在此处挂接已更改的事件。

in your codebehind, do like this:

在你的代码隐藏中,这样做:

MyList.CollectionChanged += new NotifyCollectionChangedEventHandler( this.MyCollectionChanged );


private void SortCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
  Debug.WriteLine( "Changed" );
}

#3


0  

An ObservableCollection{T} exposes the INotifyCollectionChanged.CollectionChanged event. When binding to an ItemsSource the data binding engine handles the propogation of changes from the source to the items control, but if you need to perform additional processing you can attach a handler to the CollectionChanged event and use the NotifyCollectionChangedEventArgs it provides.

ObservableCollection {T}公开INotifyCollectionChanged.CollectionChanged事件。绑定到ItemsSource时,数据绑定引擎处理从源到项控件的更改传播,但是如果需要执行其他处理,可以将处理程序附加到CollectionChanged事件并使用它提供的NotifyCollectionChangedEventArgs。

Assuming you have a public property on your view model named MyList:

假设您的视图模型上有一个名为MyList的公共属性:

public ObservableCollection<T> MyList
{
  get
  {
    if(_viewModelMyList == null)
    {
      _viewModelMyList = new ObservableCollection<T>;
      _viewModelMyList.CollectionChanged += (o, e) => 
      {
        // code to process change event can go here
        if(e.Action == NotifyCollectionChangedAction.Add)
        {
        }
      };
    }
    return _viewModelMyList;
  }
}
private ObservableCollection<T> _viewModelMyList;