在Flex中,集合类ListCollectionView及其子类是很常用的。这个类提供了两个很有用的功能,一个是过滤,一个是排序。这两个功能的实现是设置ListCollectionViewr的filterFunction和sort属性,然后调用refresh方法。然后refresh方法会在系统认为合适的时候,更新集合内容。
不过,在集合内容被更新之后,ListCollectionViewr的filterFunction和sort属性并不会被清除,而且这时向集合中插入新的元素,都要经过过滤和排序。
尤其是对过滤操作来说,我们很可能会遇到希望只对集合现有的元素一次过滤,然后在后续的插入操作中,不再进行过滤。这时,就需要在集合更新操作完成之后,将ListCollectionViewr的filterFunction属性置空。而另一方面,Flex系统并不一定会在refresh方法被调用时,就会立刻去更新集合内容,所以我们在调用refresh方法后,立刻去将filterFunction置空,可能会出现问题。根据Flex 的language reference,当集合更新完成后,集合会触发CollectionEvent事件,并且这个事件的kind属性是CollectionEventKind.REFRESH,那么我们就有以下这种解决方法。
- package mithrilon.flex {
- import mx.collections.ListCollectionView;
- import mx.events.CollectionEvent;
- import mx.events.CollectionEventKind;
- public class CollectionUtils {
- /**
- * Filter <code>ListCollectionView</code> parameter collection with <code>Function</code>
- * parameter filterFunction, then refresh the collection. When refreshing has been finished,
- * remove the filterFunction from the collection.
- *
- * NOTE:The definition of filterFunction must follow the requirement of
- * <code>ListCollectionView</code>.
- */
- public static function filterCollectionOnceAndRefresh(collection:ListCollectionView,
- filterFunction:Function):void
- {
- filterCollectionOnce(collection, filterFunction);
- collection.refresh();
- }
- /**
- * Filter <code>ListCollectionView</code> parameter collection with <code>Function</code>
- * parameter filterFunction. When refreshing has been finished, filterFunction will be
- * removed from the collection.
- *
- * NOTE:The definition of filterFunction must follow the requirement of
- * <code>ListCollectionView</code>.
- * NOTE: You should refresh the collection.
- */
- public static function filterCollectionOnce(collection:ListCollectionView,
- filterFunction:Function):void
- {
- collection.filterFunction = filterFunction;
- collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, removeCollectionFilter);
- }
- /**
- * This is a event handler for <code>CollectionEvent</code>. When the event parameter's kind
- * property is <code>CollectionEventKind.REFRESH</code>, it will remove filterFunction from
- * collection dipatching event.
- *
- * When a <code>ListCollectionView</code> object dispatches a CollectionEvent object whose
- * kind property is <code>CollectionEventKind.REFRESH</code>, it means the refreshing
- * operation on that collection has been done successfully.
- */
- public static function removeCollectionFilter(event:CollectionEvent):void {
- if (!event || event.kind != CollectionEventKind.REFRESH) {
- return;
- }
- var collection:ListCollectionView = event.target as ListCollectionView;
- collection.filterFunction = null;
- collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, removeCollectionFilter);
- //NOTE: It is NOT enough to set filterFunction to be null to remove filter from
- //collection. Calling refresh method is necessary, or some internal data containing
- //filtering info will cause some error.
- collection.refresh();
- }
- }
- }
可以如下使用此工具类。
- ……
- var collection:ArrayCollection = new ArrayCollection();
- ……
- CollectionUtils.filterCollectionOnceAndRefresh(collection, someFilter);
- ……
注意:
在CollectionUtils的62行,此处调用refresh方法的作用是将集合内部保存的一些过滤和排序的视图数据清空,因为只是将filterFunction置空,集合是不会同时清除视图数据的,这时如果对集合进行操作,就会产生一些运行时异常。而且也必须在collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, removeCollectionFilter)这段代码的后面调用refresh,否则
removeCollectionFilter可能会被重复调用。