About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Dec

    19

    虽然标题写了列表类组件,比如 DataGrid、AdvancedDataGrid、List、HorizontalList 等列表类的组件外,其实也包括其它带有项渲染器属性的组件,比如 Tree 树状列表组件也通用。项渲染器因为不同的人员翻译问题,所以也有叫项呈示器、项呈现器、项显示器等等,这些无关系要,这里就叫它项渲染器(注:以下内容仅适合 FlexFrame 或继承自 FlexFrame 的第三方或自定义的组件,如 FlexLib 等)。以下以最常见的 Flex 表格类组件 DataGrid 为例,简称为 DG 或 DG 组件。

    如何遍历项渲染器

    可以先明确的给出答案,在 FlexFrame 中的列表类组件是无法遍历项渲染器的。原因如下:

    比如表格类组件 DG 有100行,即 100 个数据项,表格能看到 10 行,其它 90 行需要通过滚动条才能看到。其实这时候 DG 组件的自定义项渲染器并不是 100 个,它很可能只有 12 个 或 14 个,它只会比表格可见行数多出那么几行,在表格滚动时会重复利用相同的项渲染器对象进行渲染不同的数据项。重复利用相同的显示对象是FLEX为了节约系统资源,这也是 Flex 框架在开发大型 RIA 应用时高效的原因之一(仔细观察的开发者会发现,当 DG 组件的滚动条往下拖动时,列表中的项渲染器是一行一行的往上移动的,不是以像素为单位连续移动的)。因为根本不存在 100 个项渲染器,所以开发者也是不可能循环遍历每一个项渲染器的,它们只是相同的显示对象在滚动时,被重复利用用来显示不同的数据罢了。

    那么开发者需要遍历项渲染器时该怎么办?当开发者提出这个问题的时候,一定是遇到了需要针对外观进行设置的时候,因为项渲染器的作用仅仅只是用来显示数据罢了,所以这个问题其实就是如何批量的动态修改或设置每一个项渲染器的外观。所以答案很明确,其实只是在项渲染器中自定义业务逻辑,根据不同的数据来显示不同的外观。开发者并不需要写一个循环体遍历项渲染器,也不需要遍历数据项。

    如何遍历项渲染器的行和列的索引值

    在一般情况下,当注册了 itemClick 类似的事件后,点击某个单元格,即某个项渲染器时,itemClick 事件对象会自动包含行和列的索引值,开发者很容易获得这些值;可是在没有触发任何事件的情况下,如何获遍历所有项渲染器行和列的索引值呢?答案其实就在上面一个问题中,因为开发者不能遍历项渲染器,但却可以遍历所有的数据项,每一个数据项在项渲染器中通过 data 属性引用,所以这个data 引用的 Object 实际上包含了所有的行和列和索引值。

    比如,当项渲染器所在的行或列被重新调整位置时,这个 data 属性对象的行和列的索引值将自动更新(这是 FlexFrame 中典型的基于事件的 MVC 设计模式,data 就是M,DG 组件就是V,当用户重置行和列或手动修改字段数据,或从外部返回数据时它就用包含的 C 处理item,并通过 V 再次显示给用户,FlexFrame 中的组件就是如此的强大,早先的 Adobe 的工程师们已经将性能、功能,和开发成本全部考虑进去了)。虽然可以遍历所有数据项,但大多数情况下我们是不需要遍历所有数据项的,因为开发者获取索引值的绝大多情况是为了用于当前对象的项渲染器中,所以只需要在项渲染器中直接读取即可。

    为什么有时候数据更新了,但视觉组件上却未更新

    FlexFrame 是非常考虑性能、功能和开发成本的框架,并且适用于大型的 RIA 类型的项目开发,如果当数据量非常大的情况下,如果每个数据更新时,视图全部更新,那么这将是非常占用资源的。所以 Adobe 的工程师们允许开发者们侦听 dataChange 事件,单个的刷新项渲染器;或对数据源调用 refresh() 方法,以便一次性刷新同步所有数据项和视图。

    为什么以上资料不适用于其它框架类组件

    以上资料内容仅适用于 FlexFrame (包括 MX 和 Spark)或继承自 FlexFrame 的自定义的组件或第三方组件,如 FlexLib 等,但它并不一定适用于其它官方或非官方的 UI 组件框架类。以 Adobe 官方的另一套 Flash CS X 系统内置的轻量级 fl.* 包的组件框架为例,同样包括了表格系列组件 DataGrid  或 List 等组件,以及继承自这个 fl.* 包的 Yahoo Astra 组件中包括的 Tree 等组件,有这些列表类组件中,所有的项渲染器事实上并不是重复利用的,而是一次性生成了所有的项渲染器,所以虽然 fl.* 包是轻量级组件,但它并不适合一次加载数百个或数千个、甚至上万的数据项。

    也正是因为其它框架类组件往往会一次性生成所有项渲染器对象,并添加到显示列表中,所以可以使用遍历项渲染器的技术;当然,因为一次性生成了所有的显示对象,这会占用非常多的系统资源,在数据量较大时往往需要使用分页显示,或分批次加载数据项(仔细观察的开发者会发现,当 fl.* 包中的 DG 组件的滚动条往下拖动时,列表中的项渲染器是以像素为单位连续的往上移动的,并不像 FlexFrame 中的 DG 组件那样是以行为单往上移动的)。

    Jul

    2

    AdvancedDataGrid 组件如果没有“根(比如拥有多个 XML 实例的 XMLList)”或“显示的根(比如将数据源 IHierarchicalCollectionView 实例 showRoot 设置为 false)”,那么在操作数据“项(行对象)”的增加或减少时,就会有滚动条显示上的一些 Bug 产生。可以对数据源使用 refresh() 方法刷新,或对 IHierarchicalCollectionView  分组数据的接口实例使用 refresh() 方法刷新。案例:PDF2SWF Pages Suite V8.x 版本的目录编辑器。

    Jan

    16

    如果直接对 DataGridColumn 对象的 itemRenderer 或 itemEditor 属性指定一个类,而没有实现 IFactory 接口,是会报以下错误的:

    1067: Class 类型值的隐式强制指令的目标是非相关类型 mx.core:IFactory。

    定义一个 DataGridColumn 对象:

    private var _1DGC:DataGridColumn = new DataGridColumn("test");

    然后通过 ClassFactory 类生成一个 NumRestrictText 工厂对象(NumRestrictText 类为一个自定义类)。

    _1DGC.itemEditor = new ClassFactory(NumRestrictText);

    Nov

    19

    Flex 列表类组件的“陷井”

    • 0 Comments
    • Flash Platform

    当 Flex 列表类如 List、DataGrid、AdvancedDataGrid 等组件时,如果使用了自定义的项渲染器,creationComplete 事件往往只会发生一次,随后的数据组件都会采用复制的方式,这种复制是连同数据一起复制的。所以这时滚动的时候组件内的数据会变的混乱,不能即时刷新。需要通过 dataChange 事件来刷新组件中的数据。如下一个最简单的 Text 组件作为一个自定义的项渲染器为例:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Text xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationComplete_fun(event);" dataChange="dataChange_fun(event);" selectable="false">
    <mx:Script>
    <![CDATA[
    private function creationComplete_fun(e:Event):void{
    htmlText = data.txt;
    }
    private function dataChange_fun(e:Event):void{
    creationComplete_fun(null);
    }
    ]]>
    </mx:Script>
    </mx:Text>

    除了以上这个“陷井”之外,列表组件还有另外的一个“陷井”。列表组件的滚动是以“行”为单位向上或向下滚动的,但是以“像素”为单位向左或向右滚动的。

    Oct

    21

    AdvancedDataGrid 组件虽然与 Tree 组件一样能支持树型结构的数据,但 AdvancedDataGrid 组件并没有像 Tree 组件那样拥有 openItems 属性,所以在判断 AdvancedDataGrid 组件所有层级数据是否全部被打开或全部被关闭需要通过其它类来实现。一般 AdvancedDataGrid 的source属性在使用树型数据结构时可通过 HierarchicalData 类的包装解析。此时 AdvancedDataGrid  类的属性 dataProvider 为实现了 IHierarchicalCollectionView 接口类的数据类型。IHierarchicalCollectionView 拥有 openNodes 属性,此时可以用来判断 AdvancedDataGrid 组件树型数据判断是否所有节点被打开方法。样例代码如:

    //myADG 为 AdvancedDataGrid 的一个实例
    //myOpenNodes 为 myADG 打开的节点数
    //执行该函数后,如 myOpenNodes 为 0,表所所有点节被关闭,否则有节点被打开
    //如需枚举所有被打开的节点,使用for each … in 遍历 obj 对象
    function getOpenNodes():void {
     myOpenNodes = 0;
     if(myADG.dataProvider is IHierarchicalCollectionView){
         var obj:Object = IHierarchicalCollectionView(myADG.dataProvider).openNodes;
      for ( var i:* in obj){
       myOpenNodes++;
      }
     }
    }