Flex 4.5: Spark DataGrid с пользовательскими ItemRenderes - PullRequest
2 голосов
/ 31 января 2012

Во-первых, извините за действительно длинный вопрос. Я пытаюсь реализовать Org.Chart, используя spark DataGrid. Данные для Org.Chart не меняются, и поэтому я жестко кодирую значения. Я должен был реализовать это Org.Chart, так как мне нужно иметь плавающее Nodes, а также соединительные линии должны быть нарисованы немного иначе по сравнению с использованием внешнего компонента. Пожалуйста, найдите следующее изображение, которого я пытаюсь достичь:

enter image description here

Вот идея:

Каждая ячейка DataGrid может быть либо connecting lines, либо actor. У меня есть пользовательский компонент MyOrgChartNode, который имеет два состояния: chartLinesState и chartActorState. Этот компонент используется как ItemRenderer для DataGrid. Вот код 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 width="100%" height="100%" includeIn="chartActorState">

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

</s:VGroup>

<s:VGroup width="100%" height="100%" includeIn="chartLinesState">

    <s:HGroup width="100%" height="100%"
              gap="0" horizontalAlign="center" verticalAlign="middle">

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

            <mx:HRule width="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
                      opaqueBackground="{_lineColor}"/>

        </s:VGroup>

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

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

                <mx:VRule height="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
                          opaqueBackground="{_lineColor}"/>

            </s:VGroup>

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

                <mx:VRule height="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
                          opaqueBackground="{_lineColor}"/>

            </s:VGroup>

        </s:VGroup>

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

            <mx:HRule width="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
                      opaqueBackground="{_lineColor}"/>

        </s:VGroup>

    </s:HGroup>

</s:VGroup>

В приведенном выше коде я использую valueObject CellRendererVO, который содержит необходимую информацию для отображения ячейки, такую ​​как видимость различных HRules и VRule присутствующих. Код для 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;
        }
    }
}

А вот код DataGrid из Application:

<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>

DataProvider для этого DataGrid - это ArrayCollection, который содержит 10 Objects со свойствами col1 - col10, где каждое свойство имеет тип CellRendererVO.

Вот вывод этой реализации:

enter image description here

Теперь вот беда

У меня есть кнопка Hide Images, как видно на изображении выше. Что нужно сделать, это то, что при нажатии на эту кнопку все изображения, показанные в Org.Chart, должны быть скрыты. Но подождите, я просто застрял с чем-то другим, а пока забудьте об этом.

Обработчик щелчка для этой кнопки выглядит следующим образом:

private function hideImagesBtn_clickHandler(event:Event):void
            {

                orgChartDP.refresh();
            }

Но при нажатии на эту кнопку я вижу странное поведение. Смотрите вывод Org.Chart при нажатии на Hide Images: enter image description here

Я не могу понять, почему это так меняется. Как вы можете видеть, делается только refresh из ArrayCollection. Почему вся структура Org.Chart меняется?

Я провел некоторое исследование по этому поводу, и одна причина, о которой я могу подумать, это только reusable функция ItemRenderer с. Но, однако, эта причина по-прежнему не распространяется на изменение Org.Chart.

Буду признателен за любую помощь в решении этой проблемы, также спасибо, что пришли сюда.

Спасибо, Анжи

1 Ответ

0 голосов
/ 08 февраля 2012

Извините, но я не до конца понял проблему, возможно, полный источник проекта мог бы помочь, и объяснить лучше, что происходит и что вы ожидаете.

Есть только несколько советов, которые я могу дать вам, как правило, на основе опубликованных вами исходных кодов.

Лучше не работать с государствами, в которых много ошибок, и я бы также подумал о политике создания детей, которая иногда может привести к ошибкам.

Надеюсь, вы найдете то, что ищете.

...