此文章的目的是将自己解决问题的方法写出来,对于一个菜鸟来说,希望得到指点和批评


    那么……


    前一阵子在做一个模块时,要求显示在列表中的数据根据设备的大类和小类形成树状结构,这个当然要用XML来组织数据源啦。像这样

    wKioL1N8ZRLjrfVkAABGL1EEXAw736.jpg


    于是想到了“mx.collections.GroupingCollection2”,其设定grouping组,就能在AdvancedDataGrid中自动呈现树状结构。

    

…………
var xmlData : XML = new XML(strXML);
var xmlList : XMLList = new XMLList(xmlData.children());
m_gcEquipmentTree = new GroupingCollection2();
m_gcEquipmentTree.source = xmlList;

//列表显示分组
var tempGroup:Grouping = new Grouping();
tempGroup.fields = 
        [new GroupingField('category_Name'), new GroupingField('subclass_Name')];
m_gcEquipmentTree.grouping = tempGroup;		
m_gcEquipmentTree.refresh();
…………

    这个m_gcEquipmentTree是Bindable的,AdvancedDataGrid的dataProvider="{m_gcEquipmentTree}",不多说了。


    问题就出在refresh()上了。每次执行这个方法时,其默认是异步刷新的,且执行后,表中的滚动条总是会回到最顶。


    且最恶心的是,需求中要求每一行数据都要加上CheckBox,如果我勾选了大类的CheckBox,那么相应的要将其下所有设备都勾选起来。目前的方法是使用mx:itemRenderer,复写其中的data方法----“override public function set data(value:Object):void ”,数据源中每一行数据有一个标志,1表示选中,0表示未选中。

    

    那么在选中大类后,数据源中相应的设备的标志位都要设定为选中状态,然后数据源refresh(),以将结果呈现到表格中,否则,需要拉动滚动条,让这些数据“滚”出表格,再“滚”回来,才会刷新到最新的状态。(因为滚回来时重新访问了data方法)


    为了避免refresh()后滚动条回到顶端,我先记录了滚动条的位置,意图刷新后将其回归到原来的位置。

//    记录advanceDataGrid滚动条目前偏移量
tempNumber = adgEquipmentTree.verticalScrollPosition;
……………………刷新动作
//    恢复
adgEquipmentTree.verticalScrollPosition = tempNumber;

    于是问题出现了,由于refresh()是异步的(我在data方法中操作涉及数据源xml的子级数据,不能使用同步,且同步有一个坏处,会频繁的闪烁,因为mx:itemRenderer的效率问题)


    确实达到了滚动条不动的效果,继续向下滚动没有问题,但是如果向上滚动,由于每次data方法接收的参数value,都是大类数据,于是向上滚动多少行,就有多少条重复的大类数据,且高亮显示的行也是错误的。(从现象看,因为xml树是向下展开的,所以这个控件大概不能从最低级的节点开始构建要显示的数据,所以导致数据显示混乱)

    是不是很恶心的问题。请注意第一行没有标题的就是大类

wKioL1N8ZZXRB3qVAAA11HepA4g419.jpg


    经过跟踪源码,找到一个解决方案:

public function classButton_ClickHandler(selected:int, equipmentList:ArrayCollection):void{
				
        m_gcEquipmentTree.addEventListener(CollectionEvent.COLLECTION_CHANGE, dispatchCollectionEventsCallBack);
				
				var sel:Boolean = selected==1?true:false;
				
				tempNumber = adgEquipmentTree.verticalScrollPosition;
				
				out:for(var x:int=0 ; x<m_acEquipmentList.length ; x++){
					inner:for(var y:int=0 ; y<equipmentList.length ; y++){
						if(m_acEquipmentList[x].id == equipmentList[y]){
							m_acEquipmentList[x].selected = sel;
						}
					}
				}
				
				m_gcEquipmentTree.refresh(false,true);
			
			}
			
			
			/**
			 * 设备列表刷新后触发函数
			 * dispatchCollectionEvents 
			 */
			private function dispatchCollectionEventsCallBack(event:Event):void{
				
				adgEquipmentTree.verticalScrollPosition = tempNumber;
				
				m_gcEquipmentTree.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dispatchCollectionEventsCallBack);
			}

    classButton_ClickHandler是大类按钮点击后访问的函数。

    refreash()执行完成后,会派发一个type为“CollectionEvent.COLLECTION_CHANGE
”的事件,监听这个事件,而后再调整滚动条的位置,这下数据正常了。




遗留问题:

    1、每次都要addEventListener然后removeEventListener

    2、原来大类的选择使用的也是checkbox,现在被我改成按钮了。因为使用GroupingCollection2,所以大小类的行是自动生成的(数据源是一条条设备),如果我将一个大类下的所有设备勾选都去掉,大类上的勾选无法去掉,因为我无法给大类的数据源上设定标志位,即使设定了,refreash()后,还是会清楚设定的结果。