Flex 4.5:带有自定义 ItemRenderes 的 Spark DataGrid

Posted

技术标签:

【中文标题】Flex 4.5:带有自定义 ItemRenderes 的 Spark DataGrid【英文标题】:Flex 4.5: Spark DataGrid with custom ItemRenderes 【发布时间】:2012-02-23 06:34:50 【问题描述】:

首先对这个非常冗长的问题表示抱歉。我正在尝试使用火花DataGrid 实现Org.ChartOrg.Chart 的数据没有改变,因此我对这些值进行了硬编码。我必须实现这个Org.Chart,因为我需要浮动Nodes,并且与使用外部组件相比,连接线的绘制应该有点不同。请找到我试图实现的以下图像:

这是一个想法:

DataGrid 的每个单元格都可以是connecting linesactor。我有一个自定义组件MyOrgChartNode,它有两种状态:chartLinesStatechartActorState。此组件用作ItemRendererDataGrid。这是MyOrgChartNode的代码:

<fx:Script>
    <![CDATA[
        import mx.controls.Alert;

        import scripts.valueObjects.ActorVO;
        import scripts.valueObjects.CellRendererVO;

        [Bindable]
        private var _cellRenderer:CellRendererVO;
        [Bindable]
        private var _lineColor:uint = 0xFF0000;
        [Bindable]
        private var _lineWidth:int = 1;

        override public function prepare(hasBeenRecycled:Boolean):void
        
            if (data != null)
            
                this.height = parseInt(data['cellHeight']);

                if (columnIndex == 1 || columnIndex == 3)
                
                    this.width = 50;
                

                currentState = (data[column.dataField] as CellRendererVO).stateName;    
            
        

        protected function orgChartNode_clickHandler(event:MouseEvent):void
        
            // TODO Auto-generated method stub

        

    ]]>
</fx:Script>

<s:states>

    <s:State name="chartLinesState" />

    <s:State name="chartActorState" />

</s:states>

<s:VGroup   includeIn="chartActorState">

    <myOrgChart:OrgChartNode id="orgChartNode"   click="orgChartNode_clickHandler(event)"
                             nodeActor="(data[column.dataField] as CellRendererVO).nodeActor" />

</s:VGroup>

<s:VGroup   includeIn="chartLinesState">

    <s:HGroup  
              gap="0" horizontalAlign="center" verticalAlign="middle">

        <s:VGroup id="horizontalLeftLine"  
                  horizontalAlign="center" verticalAlign="middle"
                  visible="(data[column.dataField] as CellRendererVO).hasHorizontalLeftLine">

            <mx:HRule  strokeWidth="_lineWidth" strokeColor="_lineColor"
                      opaqueBackground="_lineColor"/>

        </s:VGroup>

        <s:VGroup  gap="0" horizontalAlign="center"
                  verticalAlign="middle"
                  includeInLayout="(data[column.dataField] as CellRendererVO).hasVerticalTopLine || (data[column.dataField] as CellRendererVO).hasVerticalBottomLine">

            <s:VGroup id="verticalTopLine"  verticalAlign="middle"
                      visible="(data[column.dataField] as CellRendererVO).hasVerticalTopLine">

                <mx:VRule  strokeWidth="_lineWidth" strokeColor="_lineColor"
                          opaqueBackground="_lineColor"/>

            </s:VGroup>

            <s:VGroup id="verticalBottomLine"  verticalAlign="middle"
                      visible="(data[column.dataField] as CellRendererVO).hasVerticalBottomLine">

                <mx:VRule  strokeWidth="_lineWidth" strokeColor="_lineColor"
                          opaqueBackground="_lineColor"/>

            </s:VGroup>

        </s:VGroup>

        <s:VGroup id="horizontalRightLine"  
                  horizontalAlign="center" verticalAlign="middle"
                  visible="(data[column.dataField] as CellRendererVO).hasHorizontalRightLine">

            <mx:HRule  strokeWidth="_lineWidth" strokeColor="_lineColor"
                      opaqueBackground="_lineColor"/>

        </s:VGroup>

    </s:HGroup>

</s:VGroup>

在上面的代码中,我使用了valueObjectCellRendererVO,其中包含显示单元格所需的信息,例如不同HRulesVRule 存在的可见性。 CellRendererVO 的代码在这里:

package scripts.valueObjects

    public class CellRendererVO extends Object
    
        private var _hasVerticalTopLine:Boolean;
        private var _hasVerticalBottomLine:Boolean;
        private var _hasHorizontalLeftLine:Boolean;
        private var _hasHorizontalRightLine:Boolean;
        private var _nodeActor:ActorVO;
        private var _stateName:String;

        public function CellRendererVO(hasVerticalTopLine:Boolean = false, hasVerticalBottomLine:Boolean = false,
            hasHorizontalLeftLine:Boolean = false, hasHorizontalRightLine:Boolean = false,
            nodeActor:ActorVO = null, stateName:String = "chartLinesState"
            )
        
            this.hasVerticalTopLine = hasVerticalTopLine;
            this.hasVerticalBottomLine = hasVerticalBottomLine;
            this.hasHorizontalLeftLine = hasHorizontalLeftLine;
            this.hasHorizontalRightLine = hasHorizontalRightLine;
            this.nodeActor = nodeActor;
            this.stateName = stateName;
        

        public function get hasVerticalTopLine():Boolean
        
            return _hasVerticalTopLine;
        

        public function set hasVerticalTopLine(value:Boolean):void
        
            _hasVerticalTopLine = value;
        

        public function get hasVerticalBottomLine():Boolean
        
            return _hasVerticalBottomLine;
        

        public function set hasVerticalBottomLine(value:Boolean):void
        
            _hasVerticalBottomLine = value;
        

        public function get hasHorizontalLeftLine():Boolean
        
            return _hasHorizontalLeftLine;
        

        public function set hasHorizontalLeftLine(value:Boolean):void
        
            _hasHorizontalLeftLine = value;
        

        public function get hasHorizontalRightLine():Boolean
        
            return _hasHorizontalRightLine;
        

        public function set hasHorizontalRightLine(value:Boolean):void
        
            _hasHorizontalRightLine = value;
        

        public function get nodeActor():ActorVO
        
            return _nodeActor;
        

        public function set nodeActor(value:ActorVO):void
        
            _nodeActor = value;
        

        public function get stateName():String
        
            return _stateName;
        

        public function set stateName(value:String):void
        
            _stateName = value;
        
    

如您所见,有不同的布尔变量用于获取连接线,还有另一个 valueObject ActorVO 具有 actor 数据。代码如下:

package scripts.valueObjects

    public class ActorVO extends Object
    
        private var _id:int;
        private var _fullName:String;
        private var _imageSource:String;
        private var _beta1:Number;
        private var _beta2:Number;
        private var _beta3:Number;
        private var _nationality:String;
        private var _education:String;
        private var _gender:String;
        private var _displayName:String;
        private var _progress:Number;
        private var _showImage:Boolean;

        public function ActorVO(id:int = -1, fullName:String = "Full Name", imageSource:String = "",
            beta1:Number = -1, beta2:Number = -1, beta3:Number = -1, nationality:String = "India",
            gender:String = "M", progress:Number = 10, education:String = "", showImage:Boolean = true)
        
            this.id = id;
            this.fullName = fullName;
            this.imageSource = imageSource;
            this.beta1 = beta1;
            this.beta2 = beta2;
            this.beta3 = beta3;
            this.nationality = nationality;
            this.gender = gender;
            this.progress = progress;
            this.education = education;
            this.showImage = showImage;
        

        public function copyData(actor:ActorVO):void
        
            this.id = actor.id;
            this.fullName = actor.fullName;
            this.imageSource = actor.imageSource;
            this.beta1 = actor.beta1;
            this.beta2 = actor.beta2;
            this.beta3 = actor.beta3;
            this.nationality = actor.nationality;
            this.gender = actor.gender;
            this.progress = actor.progress;
            this.education = actor.education;
            this.showImage = showImage
        

        public function get id():int
        
            return _id;
        

        public function set id(value:int):void
        
            _id = value;
        

        public function get fullName():String
        
            return _fullName;
        

        public function set fullName(value:String):void
        
            _fullName = value;
            displayName = value.substring(value.lastIndexOf(" ") + 1); //return the last name in the string
        

        public function get imageSource():String
        
            return _imageSource;
        

        public function set imageSource(value:String):void
        
            /**
             * When copyData function is used, value is ./assets/images/people/
             * and hence imageSouce will be prepended with ./assets/images/people
             * hence first check if there exists path
             * */

            _imageSource = "./assets/images/people/" + value;

            if (value.indexOf("./") != -1)
            
                _imageSource = value;
            
        

        public function get beta1():Number
        
            return _beta1;
        

        public function set beta1(value:Number):void
        
            _beta1 = value;
        

        public function get beta2():Number
        
            return _beta2;
        

        public function set beta2(value:Number):void
        
            _beta2 = value;
        

        public function get beta3():Number
        
            return _beta3;
        

        public function set beta3(value:Number):void
        
            _beta3 = value;
        

        public function get nationality():String
        
            return _nationality;
        

        public function set nationality(value:String):void
        
            _nationality = value;
        

        public function get education():String
        
            return _education;
        

        public function set education(value:String):void
        
            _education = value;
        

        public function get gender():String
        
            return _gender;
        

        public function set gender(value:String):void
        
            _gender = value;
        

        public function get displayName():String
        
            return _displayName;
        

        public function set displayName(value:String):void
        
            _displayName = value;
        

        public function get progress():Number
        
            return _progress;
        

        public function set progress(value:Number):void
        
            _progress = value;
        

        public function get showImage():Boolean
        
            return _showImage;
        

        public function set showImage(value:Boolean):void
        
            _showImage = value;
        
    

这是来自ApplicationDataGrid 代码:

<s:DataGrid id="orgChartDG" borderVisible="false" skinClass="skins.OrgChartDataGridSkin"
                dataProvider="orgChartDP" variableRowHeight="true">

        <s:columns>

            <s:ArrayList>

                <s:GridColumn dataField="col1" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col2" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col3" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col4" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col5" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col6" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col7" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col8" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col9" itemRenderer="customComponents.myOrgChart.TestIR" />

                <s:GridColumn dataField="col10" itemRenderer="customComponents.myOrgChart.TestIR" />

            </s:ArrayList>

        </s:columns>

    </s:DataGrid>

这个DataGridDataProvider 是一个ArrayCollection,它包含10 个Objects 属性col1 - col10,其中每个属性的类型都是CellRendererVO

这是这个实现的输出:

现在麻烦来了

我有按钮Hide Images,如上图所示。需要做的是,当单击此按钮时,必须隐藏 Org.Chart 中显示的所有图像。但是等等,我只是坚持其他事情,现在忘记这个实现。

此按钮的点击处理程序如下:

private function hideImagesBtn_clickHandler(event:Event):void
            

                orgChartDP.refresh();
            

但是,当单击此按钮时,我看到了一个奇怪的行为。单击 Hide Images 时查看 Org.Chart 的输出:

我无法弄清楚它为什么会如此变化。如您所见,只有refreshArrayCollection 正在完成。为什么Org.Chart 的整体结构发生了变化?

我对此进行了一些研究,我能想到的一个原因是ItemRenderers 的 reusable 功能。但是,这个原因仍然不适用于Org.Chart的变更。

感谢您来到这里为解决此问题提供任何帮助。

谢谢, 安吉

【问题讨论】:

我必须承认我还没有完全阅读你冗长的问题,但是为什么为了 [insert divinity of choice] 的缘故你试图将流程图塞进数据网格? 或许更有帮助:看看Kalileo。有一个免费的社区版;不过,商业许可证相当昂贵。 @RIAstar 我已经更新了我的问题。感谢您让我知道Kalileo。我想了解为什么要这样绘制(就我而言)。我希望这次学习可以帮助我详细了解 flex ItemRenderers。 你为什么要使用 Datagrid 呢?你应该有一个完全不同类型的 Object 。 DG 中的渲染器。构建这样一个组织结构图可能不是世界上最好的主意。我知道我可能听起来很奇怪,但组织结构图不是数据网格。您应该从 canvas/uiComponent 开始从头开始创建组件,以避免刷新问题和性能问题。 @Anji google 上有一些不错的组织结构图示例。您所要做的就是稍微研究一下它们,如果您了解 core 或 flex,那么您就会知道 datagrid 不是最佳选择。这里有一些链接blog.frankula.com/?p=148和coolestflex.blogspot.com/2008/10/… 【参考方案1】:

抱歉,我没有完全理解这个问题,也许完整的项目来源可以提供帮助,并更好地解释正在发生的事情以及您期望发生的事情。

根据您发布的源代码,我一般只能给您一些提示。

你最好不要与那里有很多错误的州一起工作,我也想谈谈儿童创作政策女巫有时也会导致错误。

希望你能找到你要找的东西。

【讨论】:

以上是关于Flex 4.5:带有自定义 ItemRenderes 的 Spark DataGrid的主要内容,如果未能解决你的问题,请参考以下文章

Flex tree加三状态的Checkbox

flex 覆盖公共函数集数据

Flex-Flow Column Wrap - 带有标题的图标

TabNavigator 无法处理 Flex 4.5 中的禁用子级

Flex 4.5 (Hero) s:Datagrid RowCount

Flex 4 从自定义组件调度自定义事件(为啥 flex 将自定义事件转换为 mouseevent)