Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Flex (http://www.flasher.ru/forum/forumdisplay.php?f=84)
-   -   Вложенные итемРендереры (http://www.flasher.ru/forum/showthread.php?t=212755)

Astraport 22.04.2016 10:39

Вложенные итемРендереры
 
Я надеюсь что здесь ещё пишут на Флексе)

У меня List со сложным итемрендерером, внутри которого ещё два итемрендерера. Постоянно происходит путаница данных, потому что датапровайдер внутренних итемрендереров создается налету из первого итемрендерера.
Мне что в корневом классе создавать Vector.<ArrayCollection> для всех вложенных данных?

http://i.stack.imgur.com/1ZzjY.png

Astraport 26.04.2016 18:59

Интересно, тут ещё остались специалисты по Флексу?
Похоже окончательно технология загнулась...

Ну да ладно, просто мучаюсь который день и никак не найду приемлемого решения. Никак не разберусь как правильно организовать данные.
Итак вот есть драгабл List
Код AS3:

[Bindable] public static var posts:ArrayCollection = new ArrayCollection();
[Bindable] private var dragit:Boolean = false;
protected function lst_itemClickHandler(evt:ItemClickEvent):void {
                if (evt.label == 'mousedown') {
                    dragit = false;
                    return;
                }
                if (evt.label == 'mouseup') {
                    dragit = true;
                    return;
                }
            }
<s:List id="list" width="100%" height="100%" dataProvider="{posts}" itemRenderer="postIR" selectedIndex="0" dragEnabled="{dragit}" dragMoveEnabled="true" dropEnabled="true" useVirtualLayout="false"/>

В нём итемрендерер postIR с кучей кнопок, картинок и парой других итемрендеров.
Вот postIR
Код AS3:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:s="library://ns.adobe.com/flex/spark"
                xmlns:mx="library://ns.adobe.com/flex/mx"
                xmlns:c="*"
                autoDrawBackground="true" creationComplete="itemrenderer1_creationCompleteHandler(event)" maxHeight="120">
    <fx:Script>
        <![CDATA[
            [Bindable] private var index:int;
            [Bindable] private var socDP:ArrayCollection;
protected function itemrenderer1_creationCompleteHandler(event:FlexEvent):void
            {
                index = ((this.owner as List).dataProvider as ArrayCollection).getItemIndex(data);
 
                socDP = Copypaste.socialVector[index] as ArrayCollection;
                soc.addEventListener(ItemClickEvent.ITEM_CLICK, soc_itemClickHandler);
            }
//Deleted some code
]]>
    </fx:Script>
    <c:CheckList id="soc" width="100%" height="100%" itemRenderer="socIR" mouseDown="txt_mouseDownHandler(event)" mouseUp="soc_mouseUpHandler(event)"
            dataProvider="{socDP}" allowMultipleSelection="true" useVirtualLayout="false" click="soc_clickHandler(event)">
        <c:layout>
            <s:TileLayout requestedColumnCount="3" verticalAlign="top" padding="5"/>
        </c:layout>
    </c:CheckList>
    //Deleted some code
</s:ItemRenderer>

А вот внутренний socIR
Код AS3:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:s="library://ns.adobe.com/flex/spark"
                xmlns:mx="library://ns.adobe.com/flex/mx"
                autoDrawBackground="true" click="itemrenderer1_clickHandler(event)" creationComplete="itemrenderer1_creationCompleteHandler(event)">
    <s:layout>
        <s:HorizontalLayout verticalAlign="middle" padding="5"/>
    </s:layout>
    <s:states>
        <s:State name="normal"/>
        <s:State name="selected"/>
    </s:states>
    <fx:Script>
        <![CDATA[
 
            protected function itemrenderer1_clickHandler(event:MouseEvent):void
            {
                if (this.selected) {
                    data.selected = true;
                } else {
                    data.selected = false;
                } 
 
                var parentList:List = owner as List;
                var e:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK, true);
                e.item = data;
                e.index = parentList.dataProvider.getItemIndex(data);
                e.label = "selected";
                dispatchEvent(e);
            }
 
            override public function set data(value:Object):void
            {
                super.data = value;
                if (value.selected) {
                    data.selected = true;
                } else {
                    data.selected = false;
                } 
            } 
 
            protected function itemrenderer1_creationCompleteHandler(event:FlexEvent):void
            {
                if (data.selected) {
                    this.selected = true;
                } else {
                    this.selected = false;
                }
            }
        ]]>
    </fx:Script>
    <s:CheckBox id="socCheck" selected.selected="true" selected.normal="false" mouseEnabled="false"/>
    <s:Image source="{'images/socialicons/' + data.icon}"/>
    <s:Label text="{data.label}"/>
</s:ItemRenderer>

Все отлично, все работает, но ровно до тех пор пока я не начинаю драгать итемы (смена сортировки). Все выделения в SocIR пропадают. Я создал в классе где и главный список хранилище этих выделенных данных, но все равно все путается, какой-то хаос наблюдается.
Неужели нет какой-то стройной системы для организации правильной иерархии данных?
Я пробовал в data первого итемрендерера передавать объект или ArrayCollection, но это выдает ошибки или не работает.
В общем нужен любой совет или даже доработка за деньги.

http://i.stack.imgur.com/RIXlE.png

GBee 27.04.2016 14:13

Не очень понятно, как данные организованы.

В posts по идее должны хранится объекты, у каждого из которых есть какой-то массив socialVector.

То есть я бы создал класс Post, который содержит массив соцсетей.

Массив posts отдаем внешнему листу, в сеттере data postIR отдаем локальному листу этот data.socialVector как датапровайдер. Дальше все должно вроде и так работать.

itemrenderer1_creationCompleteHandler - выкинуть

Astraport 27.04.2016 19:58

GBee, привет дружище)
Проблема в том, что рендеры пересоздаются.
Да, можно хранить во внешних классах, но при перетаскивании ещё и индексы меняются и все это нужно учитывать. Все путается у меня постоянно.
Я думал может есть какие-то встроенное решение, у Флекса куча разных возможностей и свойств, но похоже придется топорно городить огород.

Добавлено через 2 часа 25 минут
Цитата:

отдаем локальному листу этот data.socialVector как датапровайдер
Ну вот я делаю практически так же.
У меня есть объект PostData который является элементом датапровайдера для главного List:
Код AS3:

package
{
        import flash.events.EventDispatcher;
        import mx.collections.ArrayCollection;
 
        [Bindable]
        public class PostData extends EventDispatcher {
                public var sort:int;
                public var uid:String;
                public var text:String;
                public var image:String;
                public var url:String;
                public var socials:Vector.<int>;
                public var res:Vector.<int>;
                public var resources:ArrayCollection;
                public var tags:String;
                public var published:Boolean;
        }
}

Параметр resources является ArrayCollection который является датапровайдером socIR. Вроде бы для каждого итемрендерера свой.
К resources привязываю другой ArrayCollection, который имеет данными такой объект:
Код AS3:

ackage
{
        import flash.events.EventDispatcher;
 
        [Bindable]
        public class ResData extends EventDispatcher
        {
                public var uid:String;
                public var name:String;
                public var url:String;
                public var social:int;
                public var tags:String;
                public var mintags:int;
                public var maxtags:int;
                public var selected:Boolean;
        }
}

Где selected отвечает за выделение итема.

Теперь как связать выделение с данными? Если кликаю по итему, то я назначаю внутри его:
Код AS3:

if (this.selected) {
                data.selected = true;
        } else {
                data.selected = false;
        }

Если так не назначать, то при драге все выделения слетают. Если так назначать, то при драге выделение не слетают, но при выделении например первого итема все первые итемы в остальных рендерах тоже выделяются. И вот как от этого избавиться непонятно.

GBee 28.04.2016 00:21

Привет!
В свое время мне очень помогла фраза "Рендереров не существует". :о)) Все дело в данных.
Я со спарком не работал, но думаю там в этом плане не сильно должно отличаться.

1) Показываем инфу.
Из PostIR навсегда выкидываем itemrenderer1_creationCompleteHandler(event:FlexEvent):void
Дальше можно через сеттер data, либо биндингом. Так как по идее в PostIR в дату приходит PostData, то можно сразу забиндить
Код AS3:

<c:CheckList id="soc" dataProvider="{data.resources}" .../>. События пока из него удалить

socIR в данном случае вообще тупой как дрова. Так же данные (ResData) либо через сеттер получаем, либо биндим (как частично уже сделано с лейблом и картинкой)
Код AS3:

<s:CheckBox id="socCheck" selected="{data.selected}" />

selected.selected="true" selected.normal="false" пока в мусорку
Код весь тоже удаляем - оставляем один мхмл.
Стейты - тоже

Тестим отображение и перетаскивание!!

Добавлено через 3 минуты
Код AS3:

override public function set data(value:Object):void
            {
                super.data = value;
                if (value.selected) {
                    data.selected = true;
                } else {
                    data.selected = false;
                } 
            }


Тут смешной парадокс :о)) в value приходит ResData, которая сразу попадает в data , ну а дальше сам понимаешь :о))

Добавлено через 20 минут
Изменение чекбоксов и дополнение отображения.
Тут все по идее просто и делается в postIR
1) Подписываемся на CHANGE у c:CheckList (Это стандартный компонент? Если нет, то лучше пока на обычный поменять лист) в обработчике пробегаем по data.resources и всем selected = false; потом бежим по массиву event.currentTarget.selectedItems каждому ему (ResData) selected = true;
Вроде должно работать.



И насчет отображения первоначального забыл. Все-таки чтобы чекбоксы не только отмечались, но и выделялись как выбранные элементы списка. Идем в postIR
1) Создаем переменную например
Код AS3:

 
[Bindable]
private var _selectedResData:Array;

2) прикручиываем к
Код AS3:

<c:CheckList id="soc" dataProvider="{data.resources}" selectedItems="{_selectedResData}" .../>.

3)оверрайдим сеттер дата у postIR
в нем, если дата пришла - создаем массивчик, бежим по дата.ресурсес и пихаем в новый массивчик РесДаты у которых селектед = труе.
И после пихаем указатель массивчика в _selectedResData. Его это будоражит, он генерит событие (или как там биндинг сделан) И выделяет нужные чекбоксы.


Короче, вот так, но это самый простой путь, который я не очень люблю. Биндинг удобен, но как-то не по нраву мне. А ну и я бы повесил биндинг на конкретные поля, которые будем использовать для отображения в итем рендерерах. Но тут не знаю, что лучше.
Код AS3:

ackage
{
        import flash.events.EventDispatcher;
 
 
        public class ResData extends EventDispatcher
        {
                public var uid:String;
                [Bindable]
                public var name:String;
                [Bindable]
                public var url:String;
                public var social:int;
                public var tags:String;
                public var mintags:int;
                public var maxtags:int;
                [Bindable]
                public var selected:Boolean;
        }
}

Код AS3:

package
{
        import flash.events.EventDispatcher;
        import mx.collections.ArrayCollection;
 
 
        public class PostData extends EventDispatcher {
                public var sort:int;
                public var uid:String;
[Bindable]
                public var text:String;
                public var image:String;
                public var url:String;
                public var socials:Vector.<int>;
                public var res:Vector.<int>;
[Bindable]
                public var resources:ArrayCollection;
                public var tags:String;
                public var published:Boolean;
        }
}


Astraport 28.04.2016 11:16

Ох... Лучше я тебе в Скайп напишу)


Часовой пояс GMT +4, время: 10:58.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.