wpf的集合controls, 都会有一个内在的viewmodel, 即ICollectionView;来支持sort ,filter, collection view 就是view model
wpf 根据data source 集合自动产生对应的collection view, ListCollectionView(IList ,OberservableCollection),BindingListCollectionView;(BindingListCollectionView 没有像ListCollectionView一样的sort能力,它使用IBindingList的sort定义,具体见:http://www.wpfmentor.com/2008/12/how-to-sort-bindinglist-using.html)
对于IEnumerable数据源,产生一个EnumerableCollectionView,可惜这个类是internal .如果ListBox.ItemSource = Ilist, 自动产生一个ListCollectionView.
用ICollectionView CollectionViewSource.GetDefaultView(object) 可以获得collection view,并且通过这个类在xaml中操作collection view.
在ListCollectionView中,有一个internal list,当用户设置sort,filter时通过这个list产生需要的enumerable在界面上展示;而不用真正修改数据源。(SourceCollection).
对于实现了INotifyPropertyChanged,INotifyCollectionChanged的数据源,如果设置IsSynchronizationCurrentItem=true; 这样就能实现view与collection view 的完全同步,通过操作collection view,也能在view中显示出来。 如CurrentItem,CurrentPosition,都是界面对应的item与position. 比如设置了filter,在原数据源中此数据index=3,在 view中显示index=2,则currentPosition =2.
附custom observable collection 实现:
public
class
MySampleClass : INotifyPropertyChanged
{
public
int
MyProperty
{
get
{
return
_myProperty;
}
set
{
if
(_myProperty == value)
return
;
_myProperty = value;
OnPropertyChanged(
"MyProperty"
);
}
}
public
interface
ICustomObservableCollection<T> : ICollection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
}
#region Implementation of INotifyPropertyChanged
public
event
PropertyChangedEventHandler PropertyChanged;
protected
virtual
void
OnPropertyChanged(PropertyChangedEventArgs e)
{
if
(PropertyChanged !=
null
)
{
PropertyChanged(
this
, e);
}
}
private
void
OnPropertyChanged(
string
propertyName)
{
OnPropertyChanged(
new
PropertyChangedEventArgs(propertyName));
}
#endregion
#region Implementation of INotifyCollectionChanged
public
event
NotifyCollectionChangedEventHandler CollectionChanged;
protected
virtual
void
OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if
(CollectionChanged !=
null
)
{
using
(BlockReentrancy())
{
CollectionChanged(
this
, e);
}
}
}
private
void
OnCollectionChanged(NotifyCollectionChangedAction action,
object
item)
OnCollectionChanged(
new
NotifyCollectionChangedEventArgs(action, item));
}
private
void
OnCollectionChanged(NotifyCollectionChangedAction action,
object
item,
int
index)
{
OnCollectionChanged(
new
NotifyCollectionChangedEventArgs(action, item, index));
}
private
void
OnCollectionReset()
OnCollectionChanged(
new
NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
.
#endregion